diff options
author | Yangbo Lu <yangbo.lu@nxp.com> | 2018-08-15 16:08:53 +0800 |
---|---|---|
committer | Hauke Mehrtens <hauke@hauke-m.de> | 2018-09-22 21:20:57 +0200 |
commit | a83eae385ab72c895e9af898a6fc392f05fe9728 (patch) | |
tree | 7b8a681e58dcc8e8403fa9913e9ce3a3d556e267 | |
parent | ad1dbc0ca304686a7f826528e674620791f34584 (diff) | |
download | upstream-a83eae385ab72c895e9af898a6fc392f05fe9728.tar.gz upstream-a83eae385ab72c895e9af898a6fc392f05fe9728.tar.bz2 upstream-a83eae385ab72c895e9af898a6fc392f05fe9728.zip |
layerscape: update linux 4.9 patches to LSDK-18.06
This patch is to update linux 4.9 patches to LSDK-18.06
release and to adjust config-4.9 accordingly.
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
23 files changed, 23929 insertions, 12438 deletions
diff --git a/target/linux/layerscape/armv8_32b/config-4.9 b/target/linux/layerscape/armv8_32b/config-4.9 index b7695891df..ff8949d4a4 100644 --- a/target/linux/layerscape/armv8_32b/config-4.9 +++ b/target/linux/layerscape/armv8_32b/config-4.9 @@ -145,6 +145,8 @@ CONFIG_CAN_RAW=y # CONFIG_CAN_SJA1000 is not set # CONFIG_CAN_SOFTING is not set # CONFIG_CAN_TI_HECC is not set +CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # CONFIG_CFS_BANDWIDTH is not set CONFIG_CGROUPS=y CONFIG_CGROUP_CPUACCT=y @@ -464,6 +466,7 @@ CONFIG_GENERIC_EARLY_IOREMAP=y CONFIG_GENERIC_IDLE_POLL_SETUP=y CONFIG_GENERIC_IO=y CONFIG_GENERIC_IRQ_CHIP=y +# CONFIG_GENERIC_IRQ_DEBUGFS is not set CONFIG_GENERIC_IRQ_SHOW=y CONFIG_GENERIC_IRQ_SHOW_LEVEL=y CONFIG_GENERIC_MSI_IRQ=y diff --git a/target/linux/layerscape/armv8_64b/config-4.9 b/target/linux/layerscape/armv8_64b/config-4.9 index caf7be72ea..c59cf6199e 100644 --- a/target/linux/layerscape/armv8_64b/config-4.9 +++ b/target/linux/layerscape/armv8_64b/config-4.9 @@ -98,6 +98,7 @@ CONFIG_ARM_GIC=y CONFIG_ARM_GIC_V2M=y CONFIG_ARM_GIC_V3=y CONFIG_ARM_GIC_V3_ITS=y +CONFIG_ARM_GIC_V3_ITS_FSL_MC=y # CONFIG_ARM_PL172_MPMC is not set CONFIG_ARM_PMU=y CONFIG_ARM_PSCI_FW=y @@ -157,6 +158,8 @@ CONFIG_CAVIUM_ERRATUM_22375=y CONFIG_CAVIUM_ERRATUM_23144=y CONFIG_CAVIUM_ERRATUM_23154=y CONFIG_CAVIUM_ERRATUM_27456=y +CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_CEPH_LIB=y # CONFIG_CEPH_LIB_PRETTYDEBUG is not set # CONFIG_CEPH_LIB_USE_DNS_RESOLVER is not set @@ -165,7 +168,7 @@ CONFIG_CFQ_GROUP_IOSCHED=y CONFIG_CGROUPS=y CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_DEVICE=y -# CONFIG_CGROUP_FREEZER is not set +CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_HUGETLB=y CONFIG_CGROUP_PERF=y CONFIG_CGROUP_PIDS=y @@ -417,6 +420,8 @@ CONFIG_FSL_BMAN_DEBUGFS=y CONFIG_FSL_DPAA2=y CONFIG_FSL_DPAA2_ETH=y CONFIG_FSL_DPAA2_ETHSW=y +# CONFIG_FSL_DPAA2_ETH_CEETM is not set +# CONFIG_FSL_DPAA2_ETH_DEBUGFS is not set # CONFIG_FSL_DPAA2_ETH_USE_ERR_QUEUE is not set CONFIG_FSL_DPAA2_EVB=y CONFIG_FSL_DPAA2_MAC=y @@ -499,6 +504,7 @@ CONFIG_GENERIC_EARLY_IOREMAP=y CONFIG_GENERIC_IDLE_POLL_SETUP=y CONFIG_GENERIC_IO=y CONFIG_GENERIC_IRQ_CHIP=y +# CONFIG_GENERIC_IRQ_DEBUGFS is not set CONFIG_GENERIC_IRQ_MIGRATION=y CONFIG_GENERIC_IRQ_SHOW=y CONFIG_GENERIC_IRQ_SHOW_LEVEL=y @@ -845,6 +851,7 @@ CONFIG_NET_FLOW_LIMIT=y CONFIG_NET_IP_TUNNEL=y CONFIG_NET_NS=y CONFIG_NET_PTP_CLASSIFY=y +CONFIG_NET_SWITCHDEV=y CONFIG_NLS=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y @@ -957,6 +964,7 @@ CONFIG_QCOM_QDF2400_ERRATUM_0065=y # CONFIG_QFMT_V2 is not set CONFIG_QMAN_CEETM_UPDATE_PERIOD=1000 CONFIG_QORIQ_CPUFREQ=y +CONFIG_QORIQ_THERMAL=y # CONFIG_QUICC_ENGINE is not set CONFIG_QUOTA=y CONFIG_QUOTACTL=y @@ -1233,4 +1241,3 @@ CONFIG_XZ_DEC_SPARC=y CONFIG_XZ_DEC_X86=y CONFIG_ZLIB_DEFLATE=y CONFIG_ZLIB_INFLATE=y -CONFIG_QORIQ_THERMAL=y diff --git a/target/linux/layerscape/patches-4.9/201-config-support-layerscape.patch b/target/linux/layerscape/patches-4.9/201-config-support-layerscape.patch index 218421265a..ea3cc702d9 100644 --- a/target/linux/layerscape/patches-4.9/201-config-support-layerscape.patch +++ b/target/linux/layerscape/patches-4.9/201-config-support-layerscape.patch @@ -1,7 +1,7 @@ -From e43dec70614b55ba1ce24dfcdf8f51e36d800af2 Mon Sep 17 00:00:00 2001 +From 0774b97305507af18f8c43efb69aa00e6c57ae90 Mon Sep 17 00:00:00 2001 From: Yangbo Lu <yangbo.lu@nxp.com> -Date: Wed, 17 Jan 2018 15:26:46 +0800 -Subject: [PATCH 01/30] config: support layerscape +Date: Fri, 6 Jul 2018 15:31:14 +0800 +Subject: [PATCH] config: support layerscape MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -19,22 +19,22 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> arch/arm/mach-imx/Kconfig | 1 + drivers/base/Kconfig | 1 + drivers/crypto/Makefile | 2 +- - drivers/net/ethernet/freescale/Kconfig | 4 ++- - drivers/net/ethernet/freescale/Makefile | 2 ++ - drivers/ptp/Kconfig | 29 +++++++++++++++++++ - drivers/rtc/Kconfig | 8 ++++++ + drivers/net/ethernet/freescale/Kconfig | 4 +- + drivers/net/ethernet/freescale/Makefile | 2 + + drivers/ptp/Kconfig | 29 +++++++++++ + drivers/rtc/Kconfig | 8 +++ drivers/rtc/Makefile | 1 + drivers/soc/Kconfig | 3 +- - drivers/soc/fsl/Kconfig | 22 ++++++++++++++ - drivers/soc/fsl/Kconfig.arm | 16 +++++++++++ - drivers/soc/fsl/Makefile | 4 +++ - drivers/soc/fsl/layerscape/Kconfig | 10 +++++++ + drivers/soc/fsl/Kconfig | 30 ++++++++++++ + drivers/soc/fsl/Kconfig.arm | 16 ++++++ + drivers/soc/fsl/Makefile | 5 ++ + drivers/soc/fsl/layerscape/Kconfig | 10 ++++ drivers/soc/fsl/layerscape/Makefile | 1 + - drivers/staging/Kconfig | 6 ++++ + drivers/staging/Kconfig | 6 +++ drivers/staging/Makefile | 3 ++ - drivers/staging/fsl-dpaa2/Kconfig | 51 +++++++++++++++++++++++++++++++++ - drivers/staging/fsl-dpaa2/Makefile | 9 ++++++ - 18 files changed, 169 insertions(+), 4 deletions(-) + drivers/staging/fsl-dpaa2/Kconfig | 65 +++++++++++++++++++++++++ + drivers/staging/fsl-dpaa2/Makefile | 9 ++++ + 18 files changed, 192 insertions(+), 4 deletions(-) create mode 100644 drivers/soc/fsl/Kconfig create mode 100644 drivers/soc/fsl/Kconfig.arm create mode 100644 drivers/soc/fsl/layerscape/Kconfig @@ -179,7 +179,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> source "drivers/soc/rockchip/Kconfig" --- /dev/null +++ b/drivers/soc/fsl/Kconfig -@@ -0,0 +1,22 @@ +@@ -0,0 +1,30 @@ +# +# Freescale SOC drivers +# @@ -199,6 +199,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + Initially only reading SVR and registering soc device are supported. + Other guts accesses, such as reading RCW, should eventually be moved + into this driver as well. ++ ++config FSL_SLEEP_FSM ++ bool ++ help ++ This driver configures a hardware FSM (Finite State Machine) for deep sleep. ++ The FSM is used to finish clean-ups at the last stage of system entering deep ++ sleep, and also wakes up system when a wake up event happens. ++ +if ARM || ARM64 +source "drivers/soc/fsl/Kconfig.arm" +endif @@ -223,7 +231,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +endif --- a/drivers/soc/fsl/Makefile +++ b/drivers/soc/fsl/Makefile -@@ -5,3 +5,7 @@ +@@ -5,3 +5,8 @@ obj-$(CONFIG_FSL_DPAA) += qbman/ obj-$(CONFIG_QUICC_ENGINE) += qe/ obj-$(CONFIG_CPM) += qe/ @@ -231,6 +239,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +obj-$(CONFIG_FSL_LS2_CONSOLE) += ls2-console/ +obj-$(CONFIG_SUSPEND) += rcpm.o +obj-$(CONFIG_LS_SOC_DRIVERS) += layerscape/ ++obj-$(CONFIG_FSL_SLEEP_FSM) += sleep_fsm.o --- /dev/null +++ b/drivers/soc/fsl/layerscape/Kconfig @@ -0,0 +1,10 @@ @@ -285,7 +294,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +obj-$(CONFIG_FSL_PPFE) += fsl_ppfe/ --- /dev/null +++ b/drivers/staging/fsl-dpaa2/Kconfig -@@ -0,0 +1,51 @@ +@@ -0,0 +1,65 @@ +# +# Freescale DataPath Acceleration Architecture Gen2 (DPAA2) drivers +# @@ -317,7 +326,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +# QBMAN_DEBUG requires some additional DPIO APIs +config FSL_DPAA2_ETH_DEBUGFS -+ depends on DEBUG_FS && FSL_QBMAN_DEBUG ++ depends on DEBUG_FS + bool "Enable debugfs support" + default n + ---help--- @@ -332,11 +341,25 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + (PFC) in the driver. + + If unsure, say N. ++ ++config FSL_DPAA2_ETH_CEETM ++ depends on NET_SCHED ++ bool "DPAA2 Ethernet CEETM QoS" ++ default n ++ ---help--- ++ Enable QoS offloading support through the CEETM hardware block. +endif + +source "drivers/staging/fsl-dpaa2/mac/Kconfig" +source "drivers/staging/fsl-dpaa2/evb/Kconfig" -+source "drivers/staging/fsl-dpaa2/ethsw/Kconfig" ++ ++config FSL_DPAA2_ETHSW ++ tristate "Freescale DPAA2 Ethernet Switch" ++ depends on FSL_DPAA2 ++ depends on NET_SWITCHDEV ++ ---help--- ++ Driver for Freescale DPAA2 Ethernet Switch. Select ++ BRIDGE to have support for bridge tools. --- /dev/null +++ b/drivers/staging/fsl-dpaa2/Makefile @@ -0,0 +1,9 @@ @@ -347,5 +370,5 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +obj-$(CONFIG_FSL_DPAA2_ETH) += ethernet/ +obj-$(CONFIG_FSL_DPAA2_MAC) += mac/ +obj-$(CONFIG_FSL_DPAA2_EVB) += evb/ -+obj-$(CONFIG_FSL_DPAA2_ETHSW) += ethsw/ +obj-$(CONFIG_PTP_1588_CLOCK_DPAA2) += rtc/ ++obj-$(CONFIG_FSL_DPAA2_ETHSW) += ethsw/ diff --git a/target/linux/layerscape/patches-4.9/202-core-linux-support-layerscape.patch b/target/linux/layerscape/patches-4.9/202-core-linux-support-layerscape.patch index 3484fc398e..06777a3769 100644 --- a/target/linux/layerscape/patches-4.9/202-core-linux-support-layerscape.patch +++ b/target/linux/layerscape/patches-4.9/202-core-linux-support-layerscape.patch @@ -1,7 +1,7 @@ -From 67a2eceebe9dcd92a1a5f3e912340c8975c84434 Mon Sep 17 00:00:00 2001 +From f339945a8e81fff22df95284e142b79c37fd2333 Mon Sep 17 00:00:00 2001 From: Yangbo Lu <yangbo.lu@nxp.com> -Date: Wed, 17 Jan 2018 14:50:41 +0800 -Subject: [PATCH 02/30] core-linux: support layerscape +Date: Thu, 5 Jul 2018 16:07:09 +0800 +Subject: [PATCH 02/32] core-linux: support layerscape This is an integrated patch for layerscape core-linux support. @@ -17,21 +17,43 @@ Signed-off-by: stephen hemminger <stephen@networkplumber.org> Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- - drivers/base/devres.c | 66 ++++++++++++++++++++++++++++ - drivers/base/soc.c | 70 +++++++++++++++++++++++++++++ - include/linux/device.h | 19 ++++++++ - include/linux/fsl/svr.h | 97 +++++++++++++++++++++++++++++++++++++++++ - include/linux/fsl_devices.h | 3 ++ - include/linux/netdev_features.h | 2 + - include/linux/netdevice.h | 4 ++ - include/linux/skbuff.h | 2 + - include/linux/sys_soc.h | 3 ++ - include/uapi/linux/if_ether.h | 1 + - net/core/dev.c | 13 +++++- - net/core/skbuff.c | 29 +++++++++++- - net/sched/sch_generic.c | 7 +++ - 13 files changed, 313 insertions(+), 3 deletions(-) + drivers/base/devres.c | 66 ++++++ + drivers/base/soc.c | 70 ++++++ + .../net/ethernet/mellanox/mlxsw/spectrum.c | 2 +- + .../mellanox/mlxsw/spectrum_switchdev.c | 2 +- + drivers/net/ethernet/rocker/rocker_ofdpa.c | 4 +- + include/linux/device.h | 19 ++ + include/linux/dma-mapping.h | 5 + + include/linux/fsl/svr.h | 97 ++++++++ + include/linux/fsl_devices.h | 3 + + include/linux/irqdesc.h | 4 + + include/linux/irqdomain.h | 13 +- + include/linux/netdev_features.h | 2 + + include/linux/netdevice.h | 10 +- + include/linux/skbuff.h | 2 + + include/linux/sys_soc.h | 3 + + include/net/switchdev.h | 8 +- + include/uapi/linux/if_ether.h | 1 + + kernel/irq/Kconfig | 11 + + kernel/irq/Makefile | 1 + + kernel/irq/debugfs.c | 215 ++++++++++++++++++ + kernel/irq/internals.h | 22 ++ + kernel/irq/irqdesc.c | 1 + + kernel/irq/irqdomain.c | 171 ++++++++++---- + kernel/irq/manage.c | 1 + + kernel/irq/msi.c | 2 +- + net/bridge/br.c | 4 +- + net/bridge/br_fdb.c | 2 + + net/bridge/br_private.h | 7 + + net/bridge/br_switchdev.c | 33 +++ + net/core/dev.c | 30 ++- + net/core/net-sysfs.c | 20 +- + net/core/rtnetlink.c | 4 +- + net/core/skbuff.c | 29 ++- + net/sched/sch_generic.c | 7 + + 34 files changed, 809 insertions(+), 62 deletions(-) create mode 100644 include/linux/fsl/svr.h + create mode 100644 kernel/irq/debugfs.c --- a/drivers/base/devres.c +++ b/drivers/base/devres.c @@ -195,6 +217,43 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return NULL; +} +EXPORT_SYMBOL_GPL(soc_device_match); +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +@@ -859,7 +859,7 @@ mlxsw_sp_port_get_sw_stats64(const struc + return 0; + } + +-static bool mlxsw_sp_port_has_offload_stats(int attr_id) ++static bool mlxsw_sp_port_has_offload_stats(const struct net_device *dev, int attr_id) + { + switch (attr_id) { + case IFLA_OFFLOAD_XSTATS_CPU_HIT: +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +@@ -1405,7 +1405,7 @@ static void mlxsw_sp_fdb_call_notifiers( + if (learning_sync) { + info.addr = mac; + info.vid = vid; +- notifier_type = adding ? SWITCHDEV_FDB_ADD : SWITCHDEV_FDB_DEL; ++ notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE : SWITCHDEV_FDB_DEL_TO_BRIDGE; + call_switchdev_notifiers(notifier_type, dev, &info.info); + } + } +--- a/drivers/net/ethernet/rocker/rocker_ofdpa.c ++++ b/drivers/net/ethernet/rocker/rocker_ofdpa.c +@@ -1939,10 +1939,10 @@ static void ofdpa_port_fdb_learn_work(st + + rtnl_lock(); + if (learned && removing) +- call_switchdev_notifiers(SWITCHDEV_FDB_DEL, ++ call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, + lw->ofdpa_port->dev, &info.info); + else if (learned && !removing) +- call_switchdev_notifiers(SWITCHDEV_FDB_ADD, ++ call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_BRIDGE, + lw->ofdpa_port->dev, &info.info); + rtnl_unlock(); + --- a/include/linux/device.h +++ b/include/linux/device.h @@ -688,6 +688,25 @@ void __iomem *devm_ioremap_resource(stru @@ -223,6 +282,20 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> static inline int devm_add_action_or_reset(struct device *dev, void (*action)(void *), void *data) { +--- a/include/linux/dma-mapping.h ++++ b/include/linux/dma-mapping.h +@@ -164,6 +164,11 @@ int dma_mmap_from_coherent(struct device + + #ifdef CONFIG_HAS_DMA + #include <asm/dma-mapping.h> ++static inline void set_dma_ops(struct device *dev, ++ struct dma_map_ops *dma_ops) ++{ ++ dev->archdata.dma_ops = dma_ops; ++} + #else + /* + * Define the dma api to allow compilation but not linking of --- /dev/null +++ b/include/linux/fsl/svr.h @@ -0,0 +1,97 @@ @@ -336,6 +409,76 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> unsigned check_phy_clk_valid:1; /* register save area for suspend/resume */ +--- a/include/linux/irqdesc.h ++++ b/include/linux/irqdesc.h +@@ -46,6 +46,7 @@ struct pt_regs; + * @rcu: rcu head for delayed free + * @kobj: kobject used to represent this struct in sysfs + * @dir: /proc/irq/ procfs entry ++ * @debugfs_file: dentry for the debugfs file + * @name: flow handler name for /proc/interrupts output + */ + struct irq_desc { +@@ -88,6 +89,9 @@ struct irq_desc { + #ifdef CONFIG_PROC_FS + struct proc_dir_entry *dir; + #endif ++#ifdef CONFIG_GENERIC_IRQ_DEBUGFS ++ struct dentry *debugfs_file; ++#endif + #ifdef CONFIG_SPARSE_IRQ + struct rcu_head rcu; + struct kobject kobj; +--- a/include/linux/irqdomain.h ++++ b/include/linux/irqdomain.h +@@ -138,6 +138,7 @@ struct irq_domain_chip_generic; + * setting up one or more generic chips for interrupt controllers + * drivers using the generic chip library which uses this pointer. + * @parent: Pointer to parent irq_domain to support hierarchy irq_domains ++ * @debugfs_file: dentry for the domain debugfs file + * + * Revmap data, used internally by irq_domain + * @revmap_direct_max_irq: The largest hwirq that can be set for controllers that +@@ -160,6 +161,9 @@ struct irq_domain { + #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY + struct irq_domain *parent; + #endif ++#ifdef CONFIG_GENERIC_IRQ_DEBUGFS ++ struct dentry *debugfs_file; ++#endif + + /* reverse map data. The linear map gets appended to the irq_domain */ + irq_hw_number_t hwirq_max; +@@ -174,8 +178,8 @@ enum { + /* Irq domain is hierarchical */ + IRQ_DOMAIN_FLAG_HIERARCHY = (1 << 0), + +- /* Core calls alloc/free recursive through the domain hierarchy. */ +- IRQ_DOMAIN_FLAG_AUTO_RECURSIVE = (1 << 1), ++ /* Irq domain name was allocated in __irq_domain_add() */ ++ IRQ_DOMAIN_NAME_ALLOCATED = (1 << 6), + + /* Irq domain is an IPI domain with virq per cpu */ + IRQ_DOMAIN_FLAG_IPI_PER_CPU = (1 << 2), +@@ -231,6 +235,9 @@ static inline bool is_fwnode_irqchip(str + return fwnode && fwnode->type == FWNODE_IRQCHIP; + } + ++extern void irq_domain_update_bus_token(struct irq_domain *domain, ++ enum irq_domain_bus_token bus_token); ++ + static inline + struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode, + enum irq_domain_bus_token bus_token) +@@ -403,7 +410,7 @@ static inline int irq_domain_alloc_irqs( + NULL); + } + +-extern int irq_domain_alloc_irqs_recursive(struct irq_domain *domain, ++extern int irq_domain_alloc_irqs_hierarchy(struct irq_domain *domain, + unsigned int irq_base, + unsigned int nr_irqs, void *arg); + extern int irq_domain_set_hwirq_and_chip(struct irq_domain *domain, --- a/include/linux/netdev_features.h +++ b/include/linux/netdev_features.h @@ -74,6 +74,7 @@ enum { @@ -356,6 +499,24 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> for_each_set_bit(bit, (unsigned long *)mask_addr, NETDEV_FEATURE_COUNT) --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h +@@ -930,7 +930,7 @@ struct netdev_xdp { + * 3. Update dev->stats asynchronously and atomically, and define + * neither operation. + * +- * bool (*ndo_has_offload_stats)(int attr_id) ++ * bool (*ndo_has_offload_stats)(const struct net_device *dev, int attr_id) + * Return true if this device supports offload stats of this attr_id. + * + * int (*ndo_get_offload_stats)(int attr_id, const struct net_device *dev, +@@ -1167,7 +1167,7 @@ struct net_device_ops { + + struct rtnl_link_stats64* (*ndo_get_stats64)(struct net_device *dev, + struct rtnl_link_stats64 *storage); +- bool (*ndo_has_offload_stats)(int attr_id); ++ bool (*ndo_has_offload_stats)(const struct net_device *dev, int attr_id); + int (*ndo_get_offload_stats)(int attr_id, + const struct net_device *dev, + void *attr_data); @@ -1509,6 +1509,8 @@ enum netdev_priv_flags { * @if_port: Selectable AUI, TP, ... * @dma: DMA channel @@ -374,6 +535,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> unsigned short type; unsigned short hard_header_len; unsigned short min_header_len; +@@ -1938,6 +1942,8 @@ int netdev_set_prio_tc_map(struct net_de + return 0; + } + ++int netdev_txq_to_tc(struct net_device *dev, unsigned int txq); ++ + static inline + void netdev_reset_tc(struct net_device *dev) + { --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -903,6 +903,7 @@ void kfree_skb(struct sk_buff *skb); @@ -409,6 +579,37 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +const struct soc_device_attribute *soc_device_match( + const struct soc_device_attribute *matches); #endif /* __SOC_BUS_H */ +--- a/include/net/switchdev.h ++++ b/include/net/switchdev.h +@@ -46,6 +46,7 @@ enum switchdev_attr_id { + SWITCHDEV_ATTR_ID_PORT_PARENT_ID, + SWITCHDEV_ATTR_ID_PORT_STP_STATE, + SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS, ++ SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT, + SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME, + SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, + }; +@@ -60,6 +61,7 @@ struct switchdev_attr { + struct netdev_phys_item_id ppid; /* PORT_PARENT_ID */ + u8 stp_state; /* PORT_STP_STATE */ + unsigned long brport_flags; /* PORT_BRIDGE_FLAGS */ ++ unsigned long brport_flags_support; /* PORT_BRIDGE_FLAGS_SUPPORT */ + clock_t ageing_time; /* BRIDGE_AGEING_TIME */ + bool vlan_filtering; /* BRIDGE_VLAN_FILTERING */ + } u; +@@ -149,8 +151,10 @@ struct switchdev_ops { + }; + + enum switchdev_notifier_type { +- SWITCHDEV_FDB_ADD = 1, +- SWITCHDEV_FDB_DEL, ++ SWITCHDEV_FDB_ADD_TO_BRIDGE = 1, ++ SWITCHDEV_FDB_DEL_TO_BRIDGE, ++ SWITCHDEV_FDB_ADD_TO_DEVICE, ++ SWITCHDEV_FDB_DEL_TO_DEVICE, + }; + + struct switchdev_notifier_info { --- a/include/uapi/linux/if_ether.h +++ b/include/uapi/linux/if_ether.h @@ -36,6 +36,7 @@ @@ -419,9 +620,684 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> /* * These are the defined Ethernet Protocol ID's. +--- a/kernel/irq/Kconfig ++++ b/kernel/irq/Kconfig +@@ -108,4 +108,15 @@ config SPARSE_IRQ + + If you don't know what to do here, say N. + ++config GENERIC_IRQ_DEBUGFS ++ bool "Expose irq internals in debugfs" ++ depends on DEBUG_FS ++ default n ++ ---help--- ++ ++ Exposes internal state information through debugfs. Mostly for ++ developers and debugging of hard to diagnose interrupt problems. ++ ++ If you don't know what to do here, say N. ++ + endmenu +--- a/kernel/irq/Makefile ++++ b/kernel/irq/Makefile +@@ -10,3 +10,4 @@ obj-$(CONFIG_PM_SLEEP) += pm.o + obj-$(CONFIG_GENERIC_MSI_IRQ) += msi.o + obj-$(CONFIG_GENERIC_IRQ_IPI) += ipi.o + obj-$(CONFIG_SMP) += affinity.o ++obj-$(CONFIG_GENERIC_IRQ_DEBUGFS) += debugfs.o +--- /dev/null ++++ b/kernel/irq/debugfs.c +@@ -0,0 +1,215 @@ ++/* ++ * Copyright 2017 Thomas Gleixner <tglx@linutronix.de> ++ * ++ * This file is licensed under the GPL V2. ++ */ ++#include <linux/debugfs.h> ++#include <linux/irqdomain.h> ++#include <linux/irq.h> ++ ++#include "internals.h" ++ ++static struct dentry *irq_dir; ++ ++struct irq_bit_descr { ++ unsigned int mask; ++ char *name; ++}; ++#define BIT_MASK_DESCR(m) { .mask = m, .name = #m } ++ ++static void irq_debug_show_bits(struct seq_file *m, int ind, unsigned int state, ++ const struct irq_bit_descr *sd, int size) ++{ ++ int i; ++ ++ for (i = 0; i < size; i++, sd++) { ++ if (state & sd->mask) ++ seq_printf(m, "%*s%s\n", ind + 12, "", sd->name); ++ } ++} ++ ++#ifdef CONFIG_SMP ++static void irq_debug_show_masks(struct seq_file *m, struct irq_desc *desc) ++{ ++ struct irq_data *data = irq_desc_get_irq_data(desc); ++ struct cpumask *msk; ++ ++ msk = irq_data_get_affinity_mask(data); ++ seq_printf(m, "affinity: %*pbl\n", cpumask_pr_args(msk)); ++#ifdef CONFIG_GENERIC_PENDING_IRQ ++ msk = desc->pending_mask; ++ seq_printf(m, "pending: %*pbl\n", cpumask_pr_args(msk)); ++#endif ++} ++#else ++static void irq_debug_show_masks(struct seq_file *m, struct irq_desc *desc) { } ++#endif ++ ++static const struct irq_bit_descr irqchip_flags[] = { ++ BIT_MASK_DESCR(IRQCHIP_SET_TYPE_MASKED), ++ BIT_MASK_DESCR(IRQCHIP_EOI_IF_HANDLED), ++ BIT_MASK_DESCR(IRQCHIP_MASK_ON_SUSPEND), ++ BIT_MASK_DESCR(IRQCHIP_ONOFFLINE_ENABLED), ++ BIT_MASK_DESCR(IRQCHIP_SKIP_SET_WAKE), ++ BIT_MASK_DESCR(IRQCHIP_ONESHOT_SAFE), ++ BIT_MASK_DESCR(IRQCHIP_EOI_THREADED), ++}; ++ ++static void ++irq_debug_show_chip(struct seq_file *m, struct irq_data *data, int ind) ++{ ++ struct irq_chip *chip = data->chip; ++ ++ if (!chip) { ++ seq_printf(m, "chip: None\n"); ++ return; ++ } ++ seq_printf(m, "%*schip: %s\n", ind, "", chip->name); ++ seq_printf(m, "%*sflags: 0x%lx\n", ind + 1, "", chip->flags); ++ irq_debug_show_bits(m, ind, chip->flags, irqchip_flags, ++ ARRAY_SIZE(irqchip_flags)); ++} ++ ++static void ++irq_debug_show_data(struct seq_file *m, struct irq_data *data, int ind) ++{ ++ seq_printf(m, "%*sdomain: %s\n", ind, "", ++ data->domain ? data->domain->name : ""); ++ seq_printf(m, "%*shwirq: 0x%lx\n", ind + 1, "", data->hwirq); ++ irq_debug_show_chip(m, data, ind + 1); ++#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY ++ if (!data->parent_data) ++ return; ++ seq_printf(m, "%*sparent:\n", ind + 1, ""); ++ irq_debug_show_data(m, data->parent_data, ind + 4); ++#endif ++} ++ ++static const struct irq_bit_descr irqdata_states[] = { ++ BIT_MASK_DESCR(IRQ_TYPE_EDGE_RISING), ++ BIT_MASK_DESCR(IRQ_TYPE_EDGE_FALLING), ++ BIT_MASK_DESCR(IRQ_TYPE_LEVEL_HIGH), ++ BIT_MASK_DESCR(IRQ_TYPE_LEVEL_LOW), ++ BIT_MASK_DESCR(IRQD_LEVEL), ++ ++ BIT_MASK_DESCR(IRQD_ACTIVATED), ++ BIT_MASK_DESCR(IRQD_IRQ_STARTED), ++ BIT_MASK_DESCR(IRQD_IRQ_DISABLED), ++ BIT_MASK_DESCR(IRQD_IRQ_MASKED), ++ BIT_MASK_DESCR(IRQD_IRQ_INPROGRESS), ++ ++ BIT_MASK_DESCR(IRQD_PER_CPU), ++ BIT_MASK_DESCR(IRQD_NO_BALANCING), ++ ++ BIT_MASK_DESCR(IRQD_MOVE_PCNTXT), ++ BIT_MASK_DESCR(IRQD_AFFINITY_SET), ++ BIT_MASK_DESCR(IRQD_SETAFFINITY_PENDING), ++ BIT_MASK_DESCR(IRQD_AFFINITY_MANAGED), ++ BIT_MASK_DESCR(IRQD_MANAGED_SHUTDOWN), ++ ++ BIT_MASK_DESCR(IRQD_FORWARDED_TO_VCPU), ++ ++ BIT_MASK_DESCR(IRQD_WAKEUP_STATE), ++ BIT_MASK_DESCR(IRQD_WAKEUP_ARMED), ++}; ++ ++static const struct irq_bit_descr irqdesc_states[] = { ++ BIT_MASK_DESCR(_IRQ_NOPROBE), ++ BIT_MASK_DESCR(_IRQ_NOREQUEST), ++ BIT_MASK_DESCR(_IRQ_NOTHREAD), ++ BIT_MASK_DESCR(_IRQ_NOAUTOEN), ++ BIT_MASK_DESCR(_IRQ_NESTED_THREAD), ++ BIT_MASK_DESCR(_IRQ_PER_CPU_DEVID), ++ BIT_MASK_DESCR(_IRQ_IS_POLLED), ++ BIT_MASK_DESCR(_IRQ_DISABLE_UNLAZY), ++}; ++ ++static const struct irq_bit_descr irqdesc_istates[] = { ++ BIT_MASK_DESCR(IRQS_AUTODETECT), ++ BIT_MASK_DESCR(IRQS_SPURIOUS_DISABLED), ++ BIT_MASK_DESCR(IRQS_POLL_INPROGRESS), ++ BIT_MASK_DESCR(IRQS_ONESHOT), ++ BIT_MASK_DESCR(IRQS_REPLAY), ++ BIT_MASK_DESCR(IRQS_WAITING), ++ BIT_MASK_DESCR(IRQS_PENDING), ++ BIT_MASK_DESCR(IRQS_SUSPENDED), ++}; ++ ++ ++static int irq_debug_show(struct seq_file *m, void *p) ++{ ++ struct irq_desc *desc = m->private; ++ struct irq_data *data; ++ ++ raw_spin_lock_irq(&desc->lock); ++ data = irq_desc_get_irq_data(desc); ++ seq_printf(m, "handler: %pf\n", desc->handle_irq); ++ seq_printf(m, "status: 0x%08x\n", desc->status_use_accessors); ++ irq_debug_show_bits(m, 0, desc->status_use_accessors, irqdesc_states, ++ ARRAY_SIZE(irqdesc_states)); ++ seq_printf(m, "istate: 0x%08x\n", desc->istate); ++ irq_debug_show_bits(m, 0, desc->istate, irqdesc_istates, ++ ARRAY_SIZE(irqdesc_istates)); ++ seq_printf(m, "ddepth: %u\n", desc->depth); ++ seq_printf(m, "wdepth: %u\n", desc->wake_depth); ++ seq_printf(m, "dstate: 0x%08x\n", irqd_get(data)); ++ irq_debug_show_bits(m, 0, irqd_get(data), irqdata_states, ++ ARRAY_SIZE(irqdata_states)); ++ seq_printf(m, "node: %d\n", irq_data_get_node(data)); ++ irq_debug_show_masks(m, desc); ++ irq_debug_show_data(m, data, 0); ++ raw_spin_unlock_irq(&desc->lock); ++ return 0; ++} ++ ++static int irq_debug_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, irq_debug_show, inode->i_private); ++} ++ ++static const struct file_operations dfs_irq_ops = { ++ .open = irq_debug_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++void irq_add_debugfs_entry(unsigned int irq, struct irq_desc *desc) ++{ ++ char name [10]; ++ ++ if (!irq_dir || !desc || desc->debugfs_file) ++ return; ++ ++ sprintf(name, "%d", irq); ++ desc->debugfs_file = debugfs_create_file(name, 0444, irq_dir, desc, ++ &dfs_irq_ops); ++} ++ ++void irq_remove_debugfs_entry(struct irq_desc *desc) ++{ ++ if (desc->debugfs_file) ++ debugfs_remove(desc->debugfs_file); ++} ++ ++static int __init irq_debugfs_init(void) ++{ ++ struct dentry *root_dir; ++ int irq; ++ ++ root_dir = debugfs_create_dir("irq", NULL); ++ if (!root_dir) ++ return -ENOMEM; ++ ++ irq_domain_debugfs_init(root_dir); ++ ++ irq_dir = debugfs_create_dir("irqs", root_dir); ++ ++ irq_lock_sparse(); ++ for_each_active_irq(irq) ++ irq_add_debugfs_entry(irq, irq_to_desc(irq)); ++ irq_unlock_sparse(); ++ ++ return 0; ++} ++__initcall(irq_debugfs_init); +--- a/kernel/irq/internals.h ++++ b/kernel/irq/internals.h +@@ -169,6 +169,11 @@ irq_put_desc_unlock(struct irq_desc *des + + #define __irqd_to_state(d) ACCESS_PRIVATE((d)->common, state_use_accessors) + ++static inline unsigned int irqd_get(struct irq_data *d) ++{ ++ return __irqd_to_state(d); ++} ++ + /* + * Manipulation functions for irq_data.state + */ +@@ -226,3 +231,20 @@ irq_pm_install_action(struct irq_desc *d + static inline void + irq_pm_remove_action(struct irq_desc *desc, struct irqaction *action) { } + #endif ++ ++#ifdef CONFIG_GENERIC_IRQ_DEBUGFS ++void irq_add_debugfs_entry(unsigned int irq, struct irq_desc *desc); ++void irq_remove_debugfs_entry(struct irq_desc *desc); ++# ifdef CONFIG_IRQ_DOMAIN ++void irq_domain_debugfs_init(struct dentry *root); ++# else ++static inline void irq_domain_debugfs_init(struct dentry *root); ++# endif ++#else /* CONFIG_GENERIC_IRQ_DEBUGFS */ ++static inline void irq_add_debugfs_entry(unsigned int irq, struct irq_desc *d) ++{ ++} ++static inline void irq_remove_debugfs_entry(struct irq_desc *d) ++{ ++} ++#endif /* CONFIG_GENERIC_IRQ_DEBUGFS */ +--- a/kernel/irq/irqdesc.c ++++ b/kernel/irq/irqdesc.c +@@ -394,6 +394,7 @@ static void free_desc(unsigned int irq) + { + struct irq_desc *desc = irq_to_desc(irq); + ++ irq_remove_debugfs_entry(desc); + unregister_irq_proc(irq, desc); + + /* +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -31,6 +31,14 @@ struct irqchip_fwid { + void *data; + }; + ++#ifdef CONFIG_GENERIC_IRQ_DEBUGFS ++static void debugfs_add_domain_dir(struct irq_domain *d); ++static void debugfs_remove_domain_dir(struct irq_domain *d); ++#else ++static inline void debugfs_add_domain_dir(struct irq_domain *d) { } ++static inline void debugfs_remove_domain_dir(struct irq_domain *d) { } ++#endif ++ + /** + * irq_domain_alloc_fwnode - Allocate a fwnode_handle suitable for + * identifying an irq domain +@@ -117,6 +125,7 @@ struct irq_domain *__irq_domain_add(stru + irq_domain_check_hierarchy(domain); + + mutex_lock(&irq_domain_mutex); ++ debugfs_add_domain_dir(domain); + list_add(&domain->link, &irq_domain_list); + mutex_unlock(&irq_domain_mutex); + +@@ -136,6 +145,7 @@ EXPORT_SYMBOL_GPL(__irq_domain_add); + void irq_domain_remove(struct irq_domain *domain) + { + mutex_lock(&irq_domain_mutex); ++ debugfs_remove_domain_dir(domain); + + WARN_ON(!radix_tree_empty(&domain->revmap_tree)); + +@@ -156,6 +166,37 @@ void irq_domain_remove(struct irq_domain + } + EXPORT_SYMBOL_GPL(irq_domain_remove); + ++void irq_domain_update_bus_token(struct irq_domain *domain, ++ enum irq_domain_bus_token bus_token) ++{ ++ char *name; ++ ++ if (domain->bus_token == bus_token) ++ return; ++ ++ mutex_lock(&irq_domain_mutex); ++ ++ domain->bus_token = bus_token; ++ ++ name = kasprintf(GFP_KERNEL, "%s-%d", domain->name, bus_token); ++ if (!name) { ++ mutex_unlock(&irq_domain_mutex); ++ return; ++ } ++ ++ debugfs_remove_domain_dir(domain); ++ ++ if (domain->flags & IRQ_DOMAIN_NAME_ALLOCATED) ++ kfree(domain->name); ++ else ++ domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; ++ ++ domain->name = name; ++ debugfs_add_domain_dir(domain); ++ ++ mutex_unlock(&irq_domain_mutex); ++} ++ + /** + * irq_domain_add_simple() - Register an irq_domain and optionally map a range of irqs + * @of_node: pointer to interrupt controller's device tree node. +@@ -1164,43 +1205,18 @@ void irq_domain_free_irqs_top(struct irq + irq_domain_free_irqs_common(domain, virq, nr_irqs); + } + +-static bool irq_domain_is_auto_recursive(struct irq_domain *domain) +-{ +- return domain->flags & IRQ_DOMAIN_FLAG_AUTO_RECURSIVE; +-} +- +-static void irq_domain_free_irqs_recursive(struct irq_domain *domain, ++static void irq_domain_free_irqs_hierarchy(struct irq_domain *domain, + unsigned int irq_base, + unsigned int nr_irqs) + { + domain->ops->free(domain, irq_base, nr_irqs); +- if (irq_domain_is_auto_recursive(domain)) { +- BUG_ON(!domain->parent); +- irq_domain_free_irqs_recursive(domain->parent, irq_base, +- nr_irqs); +- } + } + +-int irq_domain_alloc_irqs_recursive(struct irq_domain *domain, ++int irq_domain_alloc_irqs_hierarchy(struct irq_domain *domain, + unsigned int irq_base, + unsigned int nr_irqs, void *arg) + { +- int ret = 0; +- struct irq_domain *parent = domain->parent; +- bool recursive = irq_domain_is_auto_recursive(domain); +- +- BUG_ON(recursive && !parent); +- if (recursive) +- ret = irq_domain_alloc_irqs_recursive(parent, irq_base, +- nr_irqs, arg); +- if (ret < 0) +- return ret; +- +- ret = domain->ops->alloc(domain, irq_base, nr_irqs, arg); +- if (ret < 0 && recursive) +- irq_domain_free_irqs_recursive(parent, irq_base, nr_irqs); +- +- return ret; ++ return domain->ops->alloc(domain, irq_base, nr_irqs, arg); + } + + /** +@@ -1261,7 +1277,7 @@ int __irq_domain_alloc_irqs(struct irq_d + } + + mutex_lock(&irq_domain_mutex); +- ret = irq_domain_alloc_irqs_recursive(domain, virq, nr_irqs, arg); ++ ret = irq_domain_alloc_irqs_hierarchy(domain, virq, nr_irqs, arg); + if (ret < 0) { + mutex_unlock(&irq_domain_mutex); + goto out_free_irq_data; +@@ -1296,7 +1312,7 @@ void irq_domain_free_irqs(unsigned int v + mutex_lock(&irq_domain_mutex); + for (i = 0; i < nr_irqs; i++) + irq_domain_remove_irq(virq + i); +- irq_domain_free_irqs_recursive(data->domain, virq, nr_irqs); ++ irq_domain_free_irqs_hierarchy(data->domain, virq, nr_irqs); + mutex_unlock(&irq_domain_mutex); + + irq_domain_free_irq_data(virq, nr_irqs); +@@ -1316,15 +1332,11 @@ int irq_domain_alloc_irqs_parent(struct + unsigned int irq_base, unsigned int nr_irqs, + void *arg) + { +- /* irq_domain_alloc_irqs_recursive() has called parent's alloc() */ +- if (irq_domain_is_auto_recursive(domain)) +- return 0; ++ if (!domain->parent) ++ return -ENOSYS; + +- domain = domain->parent; +- if (domain) +- return irq_domain_alloc_irqs_recursive(domain, irq_base, +- nr_irqs, arg); +- return -ENOSYS; ++ return irq_domain_alloc_irqs_hierarchy(domain->parent, irq_base, ++ nr_irqs, arg); + } + EXPORT_SYMBOL_GPL(irq_domain_alloc_irqs_parent); + +@@ -1339,10 +1351,10 @@ EXPORT_SYMBOL_GPL(irq_domain_alloc_irqs_ + void irq_domain_free_irqs_parent(struct irq_domain *domain, + unsigned int irq_base, unsigned int nr_irqs) + { +- /* irq_domain_free_irqs_recursive() will call parent's free */ +- if (!irq_domain_is_auto_recursive(domain) && domain->parent) +- irq_domain_free_irqs_recursive(domain->parent, irq_base, +- nr_irqs); ++ if (!domain->parent) ++ return; ++ ++ irq_domain_free_irqs_hierarchy(domain->parent, irq_base, nr_irqs); + } + EXPORT_SYMBOL_GPL(irq_domain_free_irqs_parent); + +@@ -1448,3 +1460,78 @@ static void irq_domain_check_hierarchy(s + { + } + #endif /* CONFIG_IRQ_DOMAIN_HIERARCHY */ ++ ++#ifdef CONFIG_GENERIC_IRQ_DEBUGFS ++static struct dentry *domain_dir; ++ ++static void ++irq_domain_debug_show_one(struct seq_file *m, struct irq_domain *d, int ind) ++{ ++ seq_printf(m, "%*sname: %s\n", ind, "", d->name); ++ seq_printf(m, "%*ssize: %u\n", ind + 1, "", ++ d->revmap_size + d->revmap_direct_max_irq); ++ seq_printf(m, "%*smapped: %u\n", ind + 1, "", d->mapcount); ++ seq_printf(m, "%*sflags: 0x%08x\n", ind +1 , "", d->flags); ++#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY ++ if (!d->parent) ++ return; ++ seq_printf(m, "%*sparent: %s\n", ind + 1, "", d->parent->name); ++ irq_domain_debug_show_one(m, d->parent, ind + 4); ++#endif ++} ++ ++static int irq_domain_debug_show(struct seq_file *m, void *p) ++{ ++ struct irq_domain *d = m->private; ++ ++ /* Default domain? Might be NULL */ ++ if (!d) { ++ if (!irq_default_domain) ++ return 0; ++ d = irq_default_domain; ++ } ++ irq_domain_debug_show_one(m, d, 0); ++ return 0; ++} ++ ++static int irq_domain_debug_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, irq_domain_debug_show, inode->i_private); ++} ++ ++static const struct file_operations dfs_domain_ops = { ++ .open = irq_domain_debug_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static void debugfs_add_domain_dir(struct irq_domain *d) ++{ ++ if (!d->name || !domain_dir || d->debugfs_file) ++ return; ++ d->debugfs_file = debugfs_create_file(d->name, 0444, domain_dir, d, ++ &dfs_domain_ops); ++} ++ ++static void debugfs_remove_domain_dir(struct irq_domain *d) ++{ ++ if (d->debugfs_file) ++ debugfs_remove(d->debugfs_file); ++} ++ ++void __init irq_domain_debugfs_init(struct dentry *root) ++{ ++ struct irq_domain *d; ++ ++ domain_dir = debugfs_create_dir("domains", root); ++ if (!domain_dir) ++ return; ++ ++ debugfs_create_file("default", 0444, domain_dir, NULL, &dfs_domain_ops); ++ mutex_lock(&irq_domain_mutex); ++ list_for_each_entry(d, &irq_domain_list, link) ++ debugfs_add_domain_dir(d); ++ mutex_unlock(&irq_domain_mutex); ++} ++#endif +--- a/kernel/irq/manage.c ++++ b/kernel/irq/manage.c +@@ -1387,6 +1387,7 @@ __setup_irq(unsigned int irq, struct irq + wake_up_process(new->secondary->thread); + + register_irq_proc(irq, desc); ++ irq_add_debugfs_entry(irq, desc); + new->dir = NULL; + register_handler_proc(irq, new); + free_cpumask_var(mask); +--- a/kernel/irq/msi.c ++++ b/kernel/irq/msi.c +@@ -310,7 +310,7 @@ int msi_domain_populate_irqs(struct irq_ + + ops->set_desc(arg, desc); + /* Assumes the domain mutex is held! */ +- ret = irq_domain_alloc_irqs_recursive(domain, virq, 1, arg); ++ ret = irq_domain_alloc_irqs_hierarchy(domain, virq, 1, arg); + if (ret) + break; + +--- a/net/bridge/br.c ++++ b/net/bridge/br.c +@@ -138,14 +138,14 @@ static int br_switchdev_event(struct not + br = p->br; + + switch (event) { +- case SWITCHDEV_FDB_ADD: ++ case SWITCHDEV_FDB_ADD_TO_BRIDGE: + fdb_info = ptr; + err = br_fdb_external_learn_add(br, p, fdb_info->addr, + fdb_info->vid); + if (err) + err = notifier_from_errno(err); + break; +- case SWITCHDEV_FDB_DEL: ++ case SWITCHDEV_FDB_DEL_TO_BRIDGE: + fdb_info = ptr; + err = br_fdb_external_learn_del(br, p, fdb_info->addr, + fdb_info->vid); +--- a/net/bridge/br_fdb.c ++++ b/net/bridge/br_fdb.c +@@ -688,6 +688,8 @@ static void fdb_notify(struct net_bridge + struct sk_buff *skb; + int err = -ENOBUFS; + ++ br_switchdev_fdb_notify(fdb, type); ++ + skb = nlmsg_new(fdb_nlmsg_size(), GFP_ATOMIC); + if (skb == NULL) + goto errout; +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -1060,6 +1060,8 @@ void nbp_switchdev_frame_mark(const stru + struct sk_buff *skb); + bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p, + const struct sk_buff *skb); ++void br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, ++ int type); + #else + static inline int nbp_switchdev_mark_set(struct net_bridge_port *p) + { +@@ -1076,6 +1078,11 @@ static inline bool nbp_switchdev_allowed + { + return true; + } ++ ++static inline void ++br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type) ++{ ++} + #endif /* CONFIG_NET_SWITCHDEV */ + + #endif +--- a/net/bridge/br_switchdev.c ++++ b/net/bridge/br_switchdev.c +@@ -55,3 +55,36 @@ bool nbp_switchdev_allowed_egress(const + return !skb->offload_fwd_mark || + BR_INPUT_SKB_CB(skb)->offload_fwd_mark != p->offload_fwd_mark; + } ++ ++static void ++br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac, ++ u16 vid, struct net_device *dev) ++{ ++ struct switchdev_notifier_fdb_info info; ++ unsigned long notifier_type; ++ ++ info.addr = mac; ++ info.vid = vid; ++ notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_DEVICE : SWITCHDEV_FDB_DEL_TO_DEVICE; ++ call_switchdev_notifiers(notifier_type, dev, &info.info); ++} ++ ++void ++br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type) ++{ ++ if (!fdb->added_by_user) ++ return; ++ ++ switch (type) { ++ case RTM_DELNEIGH: ++ br_switchdev_fdb_call_notifiers(false, fdb->addr.addr, ++ fdb->vlan_id, ++ fdb->dst->dev); ++ break; ++ case RTM_NEWNEIGH: ++ br_switchdev_fdb_call_notifiers(true, fdb->addr.addr, ++ fdb->vlan_id, ++ fdb->dst->dev); ++ break; ++ } ++} --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -6630,9 +6630,18 @@ int dev_set_mtu(struct net_device *dev, +@@ -1968,6 +1968,23 @@ static void netif_setup_tc(struct net_de + } + } + ++int netdev_txq_to_tc(struct net_device *dev, unsigned int txq) ++{ ++ if (dev->num_tc) { ++ struct netdev_tc_txq *tc = &dev->tc_to_txq[0]; ++ int i; ++ ++ for (i = 0; i < TC_MAX_QUEUE; i++, tc++) { ++ if ((txq - tc->offset) < tc->count) ++ return i; ++ } ++ ++ return -1; ++ } ++ ++ return 0; ++} ++ + #ifdef CONFIG_XPS + static DEFINE_MUTEX(xps_map_mutex); + #define xmap_dereference(P) \ +@@ -6630,9 +6647,18 @@ int dev_set_mtu(struct net_device *dev, if (new_mtu == dev->mtu) return 0; @@ -442,6 +1318,76 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> if (!netif_device_present(dev)) return -ENODEV; +--- a/net/core/net-sysfs.c ++++ b/net/core/net-sysfs.c +@@ -1021,7 +1021,6 @@ static ssize_t show_trans_timeout(struct + return sprintf(buf, "%lu", trans_timeout); + } + +-#ifdef CONFIG_XPS + static unsigned int get_netdev_queue_index(struct netdev_queue *queue) + { + struct net_device *dev = queue->dev; +@@ -1033,6 +1032,21 @@ static unsigned int get_netdev_queue_ind + return i; + } + ++static ssize_t show_traffic_class(struct netdev_queue *queue, ++ struct netdev_queue_attribute *attribute, ++ char *buf) ++{ ++ struct net_device *dev = queue->dev; ++ int index = get_netdev_queue_index(queue); ++ int tc = netdev_txq_to_tc(dev, index); ++ ++ if (tc < 0) ++ return -EINVAL; ++ ++ return sprintf(buf, "%u\n", tc); ++} ++ ++#ifdef CONFIG_XPS + static ssize_t show_tx_maxrate(struct netdev_queue *queue, + struct netdev_queue_attribute *attribute, + char *buf) +@@ -1075,6 +1089,9 @@ static struct netdev_queue_attribute que + static struct netdev_queue_attribute queue_trans_timeout = + __ATTR(tx_timeout, S_IRUGO, show_trans_timeout, NULL); + ++static struct netdev_queue_attribute queue_traffic_class = ++ __ATTR(traffic_class, S_IRUGO, show_traffic_class, NULL); ++ + #ifdef CONFIG_BQL + /* + * Byte queue limits sysfs structures and functions. +@@ -1260,6 +1277,7 @@ static struct netdev_queue_attribute xps + + static struct attribute *netdev_queue_default_attrs[] = { + &queue_trans_timeout.attr, ++ &queue_traffic_class.attr, + #ifdef CONFIG_XPS + &xps_cpus_attribute.attr, + &queue_tx_maxrate.attr, +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -3690,7 +3690,7 @@ static int rtnl_get_offload_stats(struct + if (!size) + continue; + +- if (!dev->netdev_ops->ndo_has_offload_stats(attr_id)) ++ if (!dev->netdev_ops->ndo_has_offload_stats(dev, attr_id)) + continue; + + attr = nla_reserve_64bit(skb, attr_id, size, +@@ -3731,7 +3731,7 @@ static int rtnl_get_offload_stats_size(c + + for (attr_id = IFLA_OFFLOAD_XSTATS_FIRST; + attr_id <= IFLA_OFFLOAD_XSTATS_MAX; attr_id++) { +- if (!dev->netdev_ops->ndo_has_offload_stats(attr_id)) ++ if (!dev->netdev_ops->ndo_has_offload_stats(dev, attr_id)) + continue; + size = rtnl_get_offload_stats_attr_size(attr_id); + nla_size += nla_total_size_64bit(size); --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -842,6 +842,32 @@ void napi_consume_skb(struct sk_buff *sk diff --git a/target/linux/layerscape/patches-4.9/301-arch-support-layerscape.patch b/target/linux/layerscape/patches-4.9/301-arch-support-layerscape.patch index 52dfced2b8..2985cff0b5 100644 --- a/target/linux/layerscape/patches-4.9/301-arch-support-layerscape.patch +++ b/target/linux/layerscape/patches-4.9/301-arch-support-layerscape.patch @@ -1,7 +1,7 @@ -From 45e934873f9147f692dddbb61abc088f4c8059d7 Mon Sep 17 00:00:00 2001 +From 2f2a0ab9e4b3186be981f7151a4f4f794d4b6caa Mon Sep 17 00:00:00 2001 From: Yangbo Lu <yangbo.lu@nxp.com> -Date: Wed, 17 Jan 2018 14:51:29 +0800 -Subject: [PATCH 03/30] arch: support layerscape +Date: Thu, 5 Jul 2018 16:18:37 +0800 +Subject: [PATCH 03/32] arch: support layerscape MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -20,22 +20,25 @@ Signed-off-by: Jianhua Xie <jianhua.xie@nxp.com> Signed-off-by: Horia Geantă <horia.geanta@nxp.com> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- - arch/arm/include/asm/delay.h | 16 +++++++++ - arch/arm/include/asm/io.h | 31 ++++++++++++++++++ - arch/arm/include/asm/mach/map.h | 4 +-- - arch/arm/include/asm/pgtable.h | 7 ++++ - arch/arm/kernel/bios32.c | 43 ++++++++++++++++++++++++ - arch/arm/mm/dma-mapping.c | 1 + - arch/arm/mm/ioremap.c | 7 ++++ - arch/arm/mm/mmu.c | 9 +++++ - arch/arm64/include/asm/cache.h | 2 +- - arch/arm64/include/asm/io.h | 30 +++++++++++++++++ - arch/arm64/include/asm/pci.h | 4 +++ - arch/arm64/include/asm/pgtable-prot.h | 1 + - arch/arm64/include/asm/pgtable.h | 5 +++ - arch/arm64/kernel/pci.c | 62 +++++++++++++++++++++++++++++++++++ - arch/arm64/mm/dma-mapping.c | 6 ++++ - 15 files changed, 225 insertions(+), 3 deletions(-) + arch/arm/include/asm/delay.h | 16 +++++++ + arch/arm/include/asm/dma-mapping.h | 6 --- + arch/arm/include/asm/io.h | 31 +++++++++++++ + arch/arm/include/asm/mach/map.h | 4 +- + arch/arm/include/asm/pgtable.h | 7 +++ + arch/arm/kernel/bios32.c | 43 ++++++++++++++++++ + arch/arm/mm/dma-mapping.c | 1 + + arch/arm/mm/ioremap.c | 7 +++ + arch/arm/mm/mmu.c | 9 ++++ + arch/arm64/include/asm/cache.h | 2 +- + arch/arm64/include/asm/io.h | 30 +++++++++++++ + arch/arm64/include/asm/pci.h | 4 ++ + arch/arm64/include/asm/pgtable-prot.h | 2 + + arch/arm64/include/asm/pgtable.h | 5 +++ + arch/arm64/kernel/pci.c | 62 ++++++++++++++++++++++++++ + arch/arm64/mm/dma-mapping.c | 6 +++ + arch/powerpc/include/asm/dma-mapping.h | 5 --- + arch/tile/include/asm/dma-mapping.h | 5 --- + 18 files changed, 226 insertions(+), 19 deletions(-) --- a/arch/arm/include/asm/delay.h +++ b/arch/arm/include/asm/delay.h @@ -62,6 +65,21 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> /* Loop-based definitions for assembly code. */ extern void __loop_delay(unsigned long loops); extern void __loop_udelay(unsigned long usecs); +--- a/arch/arm/include/asm/dma-mapping.h ++++ b/arch/arm/include/asm/dma-mapping.h +@@ -31,12 +31,6 @@ static inline struct dma_map_ops *get_dm + return __generic_dma_ops(dev); + } + +-static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops) +-{ +- BUG_ON(!dev); +- dev->archdata.dma_ops = ops; +-} +- + #define HAVE_ARCH_DMA_SUPPORTED 1 + extern int dma_supported(struct device *dev, u64 mask); + --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -129,6 +129,7 @@ static inline u32 __raw_readl(const vola @@ -343,6 +361,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> #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)) +@@ -68,6 +69,7 @@ + #define PAGE_HYP_DEVICE __pgprot(PROT_DEVICE_nGnRE | PTE_HYP) + + #define PAGE_S2 __pgprot(_PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_NORMAL) | PTE_S2_RDONLY) ++#define PAGE_S2_NS __pgprot(PTE_S2_MEMATTR(MT_S2_NORMAL) | PTE_S2_RDWR | PTE_TYPE_PAGE | PTE_AF) + #define PAGE_S2_DEVICE __pgprot(_PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_DEVICE_nGnRE) | PTE_S2_RDONLY | PTE_UXN) + + #define PAGE_NONE __pgprot(((_PAGE_DEFAULT) & ~PTE_VALID) | PTE_PROT_NONE | PTE_NG | PTE_PXN | PTE_UXN) --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -370,6 +370,11 @@ static inline int pmd_protnone(pmd_t pmd @@ -441,7 +467,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> #include <linux/swiotlb.h> #include <asm/cacheflush.h> -+#include <../../../drivers/staging/fsl-mc/include/mc-bus.h> ++#include <linux/fsl/mc.h> static int swiotlb __ro_after_init; @@ -461,3 +487,31 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> __iommu_setup_dma_ops(dev, dma_base, size, iommu); } +EXPORT_SYMBOL(arch_setup_dma_ops); +--- a/arch/powerpc/include/asm/dma-mapping.h ++++ b/arch/powerpc/include/asm/dma-mapping.h +@@ -91,11 +91,6 @@ static inline struct dma_map_ops *get_dm + return dev->archdata.dma_ops; + } + +-static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops) +-{ +- dev->archdata.dma_ops = ops; +-} +- + /* + * get_dma_offset() + * +--- a/arch/tile/include/asm/dma-mapping.h ++++ b/arch/tile/include/asm/dma-mapping.h +@@ -59,11 +59,6 @@ static inline phys_addr_t dma_to_phys(st + + static inline void dma_mark_clean(void *addr, size_t size) {} + +-static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops) +-{ +- dev->archdata.dma_ops = ops; +-} +- + static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) + { + if (!dev->dma_mask) diff --git a/target/linux/layerscape/patches-4.9/302-dts-support-layercape.patch b/target/linux/layerscape/patches-4.9/302-dts-support-layercape.patch index 37dc5ee5f0..36854f1937 100644 --- a/target/linux/layerscape/patches-4.9/302-dts-support-layercape.patch +++ b/target/linux/layerscape/patches-4.9/302-dts-support-layercape.patch @@ -1,7 +1,7 @@ -From 1806d342beb334c8cb0a438315ad5529262b2791 Mon Sep 17 00:00:00 2001 +From 2ba4c76bc645b7b4ff04364f294f3022d369108a Mon Sep 17 00:00:00 2001 From: Yangbo Lu <yangbo.lu@nxp.com> -Date: Wed, 17 Jan 2018 14:52:50 +0800 -Subject: [PATCH 04/30] dts: support layercape +Date: Thu, 5 Jul 2018 16:20:56 +0800 +Subject: [PATCH 04/32] dts: support layercape This is an integrated patch for layerscape dts support. @@ -27,76 +27,80 @@ Signed-off-by: Prabhakar Kushwaha <prabhakar.kushwaha@nxp.com> Signed-off-by: Ran Wang <ran.wang_1@nxp.com> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- - arch/arm/boot/dts/alpine.dtsi | 2 +- - arch/arm/boot/dts/axm55xx.dtsi | 2 +- - arch/arm/boot/dts/ecx-2000.dts | 2 +- - arch/arm/boot/dts/imx6ul.dtsi | 4 +- - arch/arm/boot/dts/keystone.dtsi | 4 +- - arch/arm/boot/dts/ls1021a-qds.dts | 21 + - arch/arm/boot/dts/ls1021a-twr.dts | 25 + - arch/arm/boot/dts/ls1021a.dtsi | 197 +++-- - arch/arm/boot/dts/mt6580.dtsi | 2 +- - arch/arm/boot/dts/mt6589.dtsi | 2 +- - arch/arm/boot/dts/mt8127.dtsi | 2 +- - arch/arm/boot/dts/mt8135.dtsi | 2 +- - arch/arm/boot/dts/rk3288.dtsi | 2 +- - arch/arm/boot/dts/sun6i-a31.dtsi | 2 +- - arch/arm/boot/dts/sun7i-a20.dtsi | 4 +- - arch/arm/boot/dts/sun8i-a23-a33.dtsi | 2 +- - arch/arm/boot/dts/sun9i-a80.dtsi | 2 +- - arch/arm64/boot/dts/freescale/Makefile | 17 + - .../boot/dts/freescale/fsl-ls1012a-2g5rdb.dts | 123 +++ - arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts | 177 ++++ - arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts | 202 +++++ - arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts | 138 ++++ - arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 602 ++++++++++++++ - arch/arm64/boot/dts/freescale/fsl-ls1043-post.dtsi | 45 + - .../boot/dts/freescale/fsl-ls1043a-qds-sdk.dts | 69 ++ - arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts | 171 +++- - .../boot/dts/freescale/fsl-ls1043a-rdb-sdk.dts | 69 ++ - .../boot/dts/freescale/fsl-ls1043a-rdb-usdpaa.dts | 117 +++ - arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts | 113 ++- - arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 308 ++++++- - arch/arm64/boot/dts/freescale/fsl-ls1046-post.dtsi | 48 ++ - .../boot/dts/freescale/fsl-ls1046a-qds-sdk.dts | 110 +++ - arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts | 363 ++++++++ - .../boot/dts/freescale/fsl-ls1046a-rdb-sdk.dts | 83 ++ - .../boot/dts/freescale/fsl-ls1046a-rdb-usdpaa.dts | 110 +++ - arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts | 218 +++++ - arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 800 ++++++++++++++++++ - arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts | 173 ++++ - arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts | 236 ++++++ - arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi | 825 ++++++++++++++++++ - arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts | 191 ++--- - arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts | 169 ++-- - arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts | 9 +- - arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi | 763 +++-------------- - arch/arm64/boot/dts/freescale/fsl-ls2081a-rdb.dts | 161 ++++ - arch/arm64/boot/dts/freescale/fsl-ls2088a-qds.dts | 162 ++++ - arch/arm64/boot/dts/freescale/fsl-ls2088a-rdb.dts | 140 ++++ - arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi | 195 +++++ - arch/arm64/boot/dts/freescale/fsl-ls208xa-qds.dtsi | 198 +++++ - arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi | 161 ++++ - arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi | 919 +++++++++++++++++++++ - .../boot/dts/freescale/qoriq-bman1-portals.dtsi | 81 ++ - arch/arm64/boot/dts/freescale/qoriq-dpaa-eth.dtsi | 73 ++ - .../boot/dts/freescale/qoriq-fman3-0-10g-0.dtsi | 43 + - .../boot/dts/freescale/qoriq-fman3-0-10g-1.dtsi | 43 + - .../boot/dts/freescale/qoriq-fman3-0-1g-0.dtsi | 42 + - .../boot/dts/freescale/qoriq-fman3-0-1g-1.dtsi | 42 + - .../boot/dts/freescale/qoriq-fman3-0-1g-2.dtsi | 42 + - .../boot/dts/freescale/qoriq-fman3-0-1g-3.dtsi | 42 + - .../boot/dts/freescale/qoriq-fman3-0-1g-4.dtsi | 42 + - .../boot/dts/freescale/qoriq-fman3-0-1g-5.dtsi | 42 + - .../boot/dts/freescale/qoriq-fman3-0-6oh.dtsi | 47 ++ - arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi | 130 +++ - .../boot/dts/freescale/qoriq-qman1-portals.dtsi | 104 +++ - arch/powerpc/boot/dts/fsl/qoriq-bman1-portals.dtsi | 10 + - arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0.dtsi | 4 +- - arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1.dtsi | 4 +- - 67 files changed, 8231 insertions(+), 1022 deletions(-) + arch/arm/boot/dts/alpine.dtsi | 2 +- + arch/arm/boot/dts/axm55xx.dtsi | 2 +- + arch/arm/boot/dts/ecx-2000.dts | 2 +- + arch/arm/boot/dts/imx6ul.dtsi | 4 +- + arch/arm/boot/dts/keystone.dtsi | 4 +- + arch/arm/boot/dts/ls1021a-qds.dts | 26 + + arch/arm/boot/dts/ls1021a-twr.dts | 25 + + arch/arm/boot/dts/ls1021a.dtsi | 284 ++++-- + arch/arm/boot/dts/mt6580.dtsi | 2 +- + arch/arm/boot/dts/mt6589.dtsi | 2 +- + arch/arm/boot/dts/mt8127.dtsi | 2 +- + arch/arm/boot/dts/mt8135.dtsi | 2 +- + arch/arm/boot/dts/rk3288.dtsi | 2 +- + arch/arm/boot/dts/sun6i-a31.dtsi | 2 +- + arch/arm/boot/dts/sun7i-a20.dtsi | 4 +- + arch/arm/boot/dts/sun8i-a23-a33.dtsi | 2 +- + arch/arm/boot/dts/sun9i-a80.dtsi | 2 +- + arch/arm64/boot/dts/freescale/Makefile | 18 + + .../boot/dts/freescale/fsl-ls1012a-2g5rdb.dts | 123 +++ + .../boot/dts/freescale/fsl-ls1012a-frdm.dts | 141 +++ + .../boot/dts/freescale/fsl-ls1012a-frwy.dts | 177 ++++ + .../boot/dts/freescale/fsl-ls1012a-qds.dts | 166 ++++ + .../boot/dts/freescale/fsl-ls1012a-rdb.dts | 102 ++ + .../arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 567 +++++++++++ + .../boot/dts/freescale/fsl-ls1043-post.dtsi | 44 + + .../dts/freescale/fsl-ls1043a-qds-sdk.dts | 71 ++ + .../boot/dts/freescale/fsl-ls1043a-qds.dts | 210 ++++- + .../dts/freescale/fsl-ls1043a-rdb-sdk.dts | 71 ++ + .../dts/freescale/fsl-ls1043a-rdb-usdpaa.dts | 117 +++ + .../boot/dts/freescale/fsl-ls1043a-rdb.dts | 152 ++- + .../arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 357 +++++-- + .../boot/dts/freescale/fsl-ls1046-post.dtsi | 48 + + .../dts/freescale/fsl-ls1046a-qds-sdk.dts | 112 +++ + .../boot/dts/freescale/fsl-ls1046a-qds.dts | 326 +++++++ + .../dts/freescale/fsl-ls1046a-rdb-sdk.dts | 85 ++ + .../dts/freescale/fsl-ls1046a-rdb-usdpaa.dts | 110 +++ + .../boot/dts/freescale/fsl-ls1046a-rdb.dts | 181 ++++ + .../arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 771 +++++++++++++++ + .../boot/dts/freescale/fsl-ls1088a-qds.dts | 137 +++ + .../boot/dts/freescale/fsl-ls1088a-rdb.dts | 200 ++++ + .../arm64/boot/dts/freescale/fsl-ls1088a.dtsi | 800 ++++++++++++++++ + .../boot/dts/freescale/fsl-ls2080a-qds.dts | 229 +---- + .../boot/dts/freescale/fsl-ls2080a-rdb.dts | 207 ++-- + .../boot/dts/freescale/fsl-ls2080a-simu.dts | 47 +- + .../arm64/boot/dts/freescale/fsl-ls2080a.dtsi | 803 ++-------------- + .../boot/dts/freescale/fsl-ls2081a-rdb.dts | 161 ++++ + .../boot/dts/freescale/fsl-ls2088a-qds.dts | 126 +++ + .../boot/dts/freescale/fsl-ls2088a-rdb.dts | 104 ++ + .../arm64/boot/dts/freescale/fsl-ls2088a.dtsi | 159 ++++ + .../boot/dts/freescale/fsl-ls208xa-qds.dtsi | 162 ++++ + .../boot/dts/freescale/fsl-ls208xa-rdb.dtsi | 136 +++ + .../arm64/boot/dts/freescale/fsl-ls208xa.dtsi | 885 ++++++++++++++++++ + .../dts/freescale/qoriq-bman-portals-sdk.dtsi | 55 ++ + .../dts/freescale/qoriq-bman-portals.dtsi | 77 ++ + .../boot/dts/freescale/qoriq-dpaa-eth.dtsi | 73 ++ + .../dts/freescale/qoriq-fman3-0-10g-0.dtsi | 43 + + .../dts/freescale/qoriq-fman3-0-10g-1.dtsi | 43 + + .../dts/freescale/qoriq-fman3-0-1g-0.dtsi | 42 + + .../dts/freescale/qoriq-fman3-0-1g-1.dtsi | 42 + + .../dts/freescale/qoriq-fman3-0-1g-2.dtsi | 42 + + .../dts/freescale/qoriq-fman3-0-1g-3.dtsi | 42 + + .../dts/freescale/qoriq-fman3-0-1g-4.dtsi | 42 + + .../dts/freescale/qoriq-fman3-0-1g-5.dtsi | 42 + + .../boot/dts/freescale/qoriq-fman3-0-6oh.dtsi | 47 + + .../boot/dts/freescale/qoriq-fman3-0.dtsi | 130 +++ + .../dts/freescale/qoriq-qman-portals-sdk.dtsi | 38 + + .../dts/freescale/qoriq-qman-portals.dtsi | 87 ++ + .../boot/dts/fsl/qoriq-bman1-portals.dtsi | 10 + + .../boot/dts/fsl/qoriq-fman3-0-10g-0.dtsi | 4 +- + .../boot/dts/fsl/qoriq-fman3-0-10g-1.dtsi | 4 +- + 70 files changed, 8051 insertions(+), 1286 deletions(-) create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls1012a-2g5rdb.dts create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts + create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls1012a-frwy.dts create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi @@ -121,7 +125,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls208xa-qds.dtsi create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi - create mode 100644 arch/arm64/boot/dts/freescale/qoriq-bman1-portals.dtsi + create mode 100644 arch/arm64/boot/dts/freescale/qoriq-bman-portals-sdk.dtsi + create mode 100644 arch/arm64/boot/dts/freescale/qoriq-bman-portals.dtsi create mode 100644 arch/arm64/boot/dts/freescale/qoriq-dpaa-eth.dtsi create mode 100644 arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-0.dtsi create mode 100644 arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-1.dtsi @@ -133,7 +138,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> create mode 100644 arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-5.dtsi create mode 100644 arch/arm64/boot/dts/freescale/qoriq-fman3-0-6oh.dtsi create mode 100644 arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi - create mode 100644 arch/arm64/boot/dts/freescale/qoriq-qman1-portals.dtsi + create mode 100644 arch/arm64/boot/dts/freescale/qoriq-qman-portals-sdk.dtsi + create mode 100644 arch/arm64/boot/dts/freescale/qoriq-qman-portals.dtsi --- a/arch/arm/boot/dts/alpine.dtsi +++ b/arch/arm/boot/dts/alpine.dtsi @@ -223,7 +229,19 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> &enet0 { tbi-handle = <&tbi0>; phy-handle = <&sgmii_phy1c>; -@@ -331,3 +344,11 @@ +@@ -239,6 +252,11 @@ + device-width = <1>; + }; + ++ nand@2,0 { ++ compatible = "fsl,ifc-nand"; ++ reg = <0x2 0x0 0x10000>; ++ }; ++ + fpga: board-control@3,0 { + #address-cells = <1>; + #size-cells = <1>; +@@ -331,3 +349,11 @@ &uart1 { status = "okay"; }; @@ -282,15 +300,30 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; --- a/arch/arm/boot/dts/ls1021a.dtsi +++ b/arch/arm/boot/dts/ls1021a.dtsi -@@ -74,17 +74,24 @@ +@@ -47,6 +47,7 @@ + + #include "skeleton64.dtsi" + #include <dt-bindings/interrupt-controller/arm-gic.h> ++#include <dt-bindings/thermal/thermal.h> + + / { + compatible = "fsl,ls1021a"; +@@ -70,21 +71,29 @@ + #address-cells = <1>; + #size-cells = <0>; + +- cpu@f00 { ++ cpu0: @f00 { compatible = "arm,cortex-a7"; device_type = "cpu"; reg = <0xf00>; - clocks = <&cluster1_clk>; + clocks = <&clockgen 1 0>; ++ #cooling-cells = <2>; }; - cpu@f01 { +- cpu@f01 { ++ cpu1: @f01 { compatible = "arm,cortex-a7"; device_type = "cpu"; reg = <0xf01>; @@ -309,7 +342,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> timer { compatible = "arm,armv7-timer"; interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, -@@ -108,11 +115,11 @@ +@@ -108,11 +117,11 @@ ranges; gic: interrupt-controller@1400000 { @@ -323,7 +356,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> <0x0 0x1404000 0x0 0x2000>, <0x0 0x1406000 0x0 0x2000>; interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>; -@@ -120,14 +127,14 @@ +@@ -120,14 +129,14 @@ }; msi1: msi-controller@1570e00 { @@ -340,7 +373,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> reg = <0x0 0x1570e08 0x0 0x8>; msi-controller; interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>; -@@ -137,11 +144,12 @@ +@@ -137,11 +146,12 @@ compatible = "fsl,ifc", "simple-bus"; reg = <0x0 0x1530000 0x0 0x10000>; interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>; @@ -354,7 +387,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> big-endian; }; -@@ -163,7 +171,7 @@ +@@ -163,7 +173,7 @@ <0x0 0x20220520 0x0 0x4>; reg-names = "ahci", "sata-ecc"; interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>; @@ -363,14 +396,19 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> dma-coherent; status = "disabled"; }; -@@ -214,41 +222,10 @@ +@@ -214,43 +224,89 @@ }; clockgen: clocking@1ee1000 { - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0x0 0x1ee1000 0x10000>; -- ++ compatible = "fsl,ls1021a-clockgen"; ++ reg = <0x0 0x1ee1000 0x0 0x1000>; ++ #clock-cells = <2>; ++ clocks = <&sysclk>; ++ }; + - sysclk: sysclk { - compatible = "fixed-clock"; - #clock-cells = <0>; @@ -401,15 +439,88 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - clock-names = "pll1cga", "pll1cga-div2", "pll1cga-div4"; - clocks = <&cga_pll1 0>, <&cga_pll1 1>, <&cga_pll1 2>; - clock-output-names = "cluster1-clk"; -- }; -+ compatible = "fsl,ls1021a-clockgen"; -+ reg = <0x0 0x1ee1000 0x0 0x1000>; -+ #clock-cells = <2>; -+ clocks = <&sysclk>; ++ tmu: tmu@1f00000 { ++ compatible = "fsl,qoriq-tmu"; ++ reg = <0x0 0x1f00000 0x0 0x10000>; ++ interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>; ++ fsl,tmu-range = <0xb0000 0xa0026 0x80048 0x30061>; ++ fsl,tmu-calibration = <0x00000000 0x0000000f ++ 0x00000001 0x00000017 ++ 0x00000002 0x0000001e ++ 0x00000003 0x00000026 ++ 0x00000004 0x0000002e ++ 0x00000005 0x00000035 ++ 0x00000006 0x0000003d ++ 0x00000007 0x00000044 ++ 0x00000008 0x0000004c ++ 0x00000009 0x00000053 ++ 0x0000000a 0x0000005b ++ 0x0000000b 0x00000064 ++ ++ 0x00010000 0x00000011 ++ 0x00010001 0x0000001c ++ 0x00010002 0x00000024 ++ 0x00010003 0x0000002b ++ 0x00010004 0x00000034 ++ 0x00010005 0x00000039 ++ 0x00010006 0x00000042 ++ 0x00010007 0x0000004c ++ 0x00010008 0x00000051 ++ 0x00010009 0x0000005a ++ 0x0001000a 0x00000063 ++ ++ 0x00020000 0x00000013 ++ 0x00020001 0x00000019 ++ 0x00020002 0x00000024 ++ 0x00020003 0x0000002c ++ 0x00020004 0x00000035 ++ 0x00020005 0x0000003d ++ 0x00020006 0x00000046 ++ 0x00020007 0x00000050 ++ 0x00020008 0x00000059 ++ ++ 0x00030000 0x00000002 ++ 0x00030001 0x0000000d ++ 0x00030002 0x00000019 ++ 0x00030003 0x00000024>; ++ #thermal-sensor-cells = <1>; ++ }; ++ ++ thermal-zones { ++ cpu_thermal: cpu-thermal { ++ polling-delay-passive = <1000>; ++ polling-delay = <5000>; ++ ++ thermal-sensors = <&tmu 0>; ++ ++ trips { ++ cpu_alert: cpu-alert { ++ temperature = <85000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ cpu_crit: cpu-crit { ++ temperature = <95000>; ++ hysteresis = <2000>; ++ type = "critical"; ++ }; ++ }; ++ ++ cooling-maps { ++ map0 { ++ trip = <&cpu_alert>; ++ cooling-device = ++ <&cpu0 THERMAL_NO_LIMIT ++ THERMAL_NO_LIMIT>; ++ }; ++ }; + }; }; - +- dspi0: dspi@2100000 { -@@ -258,7 +235,7 @@ + compatible = "fsl,ls1021a-v1.0-dspi"; + #address-cells = <1>; +@@ -258,7 +314,7 @@ reg = <0x0 0x2100000 0x0 0x10000>; interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>; clock-names = "dspi"; @@ -418,7 +529,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> spi-num-chipselects = <6>; big-endian; status = "disabled"; -@@ -271,12 +248,27 @@ +@@ -271,31 +327,48 @@ reg = <0x0 0x2110000 0x0 0x10000>; interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>; clock-names = "dspi"; @@ -445,27 +556,34 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + }; + i2c0: i2c@2180000 { - compatible = "fsl,vf610-i2c"; +- compatible = "fsl,vf610-i2c"; ++ compatible = "fsl,vf610-i2c", "fsl,ls1021a-vf610-i2c"; #address-cells = <1>; -@@ -284,7 +276,7 @@ + #size-cells = <0>; reg = <0x0 0x2180000 0x0 0x10000>; interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>; clock-names = "i2c"; - clocks = <&platform_clk 1>; + clocks = <&clockgen 4 1>; ++ fsl-scl-gpio = <&gpio3 23 0>; status = "disabled"; }; -@@ -295,7 +287,7 @@ + i2c1: i2c@2190000 { +- compatible = "fsl,vf610-i2c"; ++ compatible = "fsl,vf610-i2c", "fsl,ls1021a-vf610-i2c"; + #address-cells = <1>; + #size-cells = <0>; reg = <0x0 0x2190000 0x0 0x10000>; interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>; clock-names = "i2c"; - clocks = <&platform_clk 1>; + clocks = <&clockgen 4 1>; ++ fsl-scl-gpio = <&gpio3 23 0>; status = "disabled"; }; -@@ -306,7 +298,7 @@ +@@ -306,7 +379,7 @@ reg = <0x0 0x21a0000 0x0 0x10000>; interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>; clock-names = "i2c"; @@ -474,7 +592,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> status = "disabled"; }; -@@ -399,7 +391,7 @@ +@@ -399,7 +472,7 @@ compatible = "fsl,ls1021a-lpuart"; reg = <0x0 0x2960000 0x0 0x1000>; interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>; @@ -483,7 +601,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> clock-names = "ipg"; status = "disabled"; }; -@@ -408,7 +400,7 @@ +@@ -408,7 +481,7 @@ compatible = "fsl,ls1021a-lpuart"; reg = <0x0 0x2970000 0x0 0x1000>; interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>; @@ -492,7 +610,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> clock-names = "ipg"; status = "disabled"; }; -@@ -417,7 +409,7 @@ +@@ -417,7 +490,7 @@ compatible = "fsl,ls1021a-lpuart"; reg = <0x0 0x2980000 0x0 0x1000>; interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>; @@ -501,7 +619,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> clock-names = "ipg"; status = "disabled"; }; -@@ -426,7 +418,7 @@ +@@ -426,7 +499,7 @@ compatible = "fsl,ls1021a-lpuart"; reg = <0x0 0x2990000 0x0 0x1000>; interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>; @@ -510,7 +628,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> clock-names = "ipg"; status = "disabled"; }; -@@ -435,16 +427,26 @@ +@@ -435,16 +508,26 @@ compatible = "fsl,ls1021a-lpuart"; reg = <0x0 0x29a0000 0x0 0x1000>; interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>; @@ -539,7 +657,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> clock-names = "wdog-en"; big-endian; }; -@@ -454,8 +456,8 @@ +@@ -454,8 +537,8 @@ compatible = "fsl,vf610-sai"; reg = <0x0 0x2b50000 0x0 0x10000>; interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>; @@ -550,7 +668,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> clock-names = "bus", "mclk1", "mclk2", "mclk3"; dma-names = "tx", "rx"; dmas = <&edma0 1 47>, -@@ -468,8 +470,8 @@ +@@ -468,8 +551,8 @@ compatible = "fsl,vf610-sai"; reg = <0x0 0x2b60000 0x0 0x10000>; interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>; @@ -561,7 +679,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> clock-names = "bus", "mclk1", "mclk2", "mclk3"; dma-names = "tx", "rx"; dmas = <&edma0 1 45>, -@@ -489,16 +491,31 @@ +@@ -489,16 +572,31 @@ dma-channels = <32>; big-endian; clock-names = "dmamux0", "dmamux1"; @@ -597,16 +715,19 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> clock-names = "dcu", "pix"; big-endian; status = "disabled"; -@@ -626,6 +643,8 @@ +@@ -626,7 +724,11 @@ interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>; dr_mode = "host"; snps,quirk-frame-length-adjustment = <0x20>; + configure-gfladj; + dma-coherent; snps,dis_rxdet_inp3_quirk; ++ usb3-lpm-capable; ++ snps,dis-u1u2-when-u3-quirk; }; -@@ -634,7 +653,9 @@ + pcie@3400000 { +@@ -634,7 +736,9 @@ reg = <0x00 0x03400000 0x0 0x00010000 /* controller registers */ 0x40 0x00000000 0x0 0x00002000>; /* configuration space */ reg-names = "regs", "config"; @@ -617,7 +738,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> fsl,pcie-scfg = <&scfg 0>; #address-cells = <3>; #size-cells = <2>; -@@ -643,7 +664,7 @@ +@@ -643,7 +747,7 @@ 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 */ @@ -626,7 +747,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>, -@@ -657,7 +678,9 @@ +@@ -657,7 +761,9 @@ reg = <0x00 0x03500000 0x0 0x00010000 /* controller registers */ 0x48 0x00000000 0x0 0x00002000>; /* configuration space */ reg-names = "regs", "config"; @@ -637,7 +758,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> fsl,pcie-scfg = <&scfg 1>; #address-cells = <3>; #size-cells = <2>; -@@ -666,7 +689,7 @@ +@@ -666,7 +772,7 @@ 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 */ @@ -646,7 +767,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>, -@@ -674,5 +697,45 @@ +@@ -674,5 +780,45 @@ <0000 0 0 3 &gic GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 4 &gic GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>; }; @@ -796,8 +917,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> interrupt-controller; --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile -@@ -1,8 +1,25 @@ +@@ -1,8 +1,26 @@ +dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1012a-frdm.dtb ++dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1012a-frwy.dtb +dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1012a-qds.dtb +dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1012a-rdb.dtb +dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1012a-2g5rdb.dtb @@ -950,49 +1072,13 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts -@@ -0,0 +1,177 @@ +@@ -0,0 +1,141 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Device Tree file for Freescale LS1012A Freedom Board. + * + * Copyright 2016 Freescale Semiconductor, Inc. + * -+ * 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/; + @@ -1129,12 +1215,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + status = "okay"; +}; --- /dev/null -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts -@@ -0,0 +1,202 @@ ++++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-frwy.dts +@@ -0,0 +1,177 @@ +/* -+ * Device Tree file for Freescale LS1012A QDS Board. ++ * Device Tree file for NXP LS1012A FRWY Board. + * -+ * Copyright 2016 Freescale Semiconductor, Inc. ++ * Copyright 2018 NXP + * + * 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 @@ -1179,6 +1265,150 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#include "fsl-ls1012a.dtsi" + +/ { ++ model = "LS1012A FRWY Board"; ++ compatible = "fsl,ls1012a-frwy", "fsl,ls1012a"; ++ ++ aliases { ++ ethernet0 = &pfe_mac0; ++ ethernet1 = &pfe_mac1; ++ }; ++ ++ sys_mclk: clock-mclk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <25000000>; ++ }; ++ ++ reg_1p8v: regulator-1p8v { ++ compatible = "regulator-fixed"; ++ regulator-name = "1P8V"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ }; ++ ++ sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,widgets = ++ "Microphone", "Microphone Jack", ++ "Headphone", "Headphone Jack", ++ "Speaker", "Speaker Ext", ++ "Line", "Line In Jack"; ++ simple-audio-card,routing = ++ "MIC_IN", "Microphone Jack", ++ "Microphone Jack", "Mic Bias", ++ "LINE_IN", "Line In Jack", ++ "Headphone Jack", "HP_OUT", ++ "Speaker Ext", "LINE_OUT"; ++ ++ simple-audio-card,cpu { ++ sound-dai = <&sai2>; ++ frame-master; ++ bitclock-master; ++ }; ++ ++ simple-audio-card,codec { ++ sound-dai = <&codec>; ++ frame-master; ++ bitclock-master; ++ system-clock-frequency = <25000000>; ++ }; ++ }; ++}; ++ ++&pcie { ++ status = "okay"; ++}; ++ ++&duart0 { ++ status = "okay"; ++}; ++ ++&i2c0 { ++ status = "okay"; ++ ++ codec: sgtl5000@a { ++ compatible = "fsl,sgtl5000"; ++ #sound-dai-cells = <0>; ++ reg = <0xa>; ++ VDDA-supply = <®_1p8v>; ++ VDDIO-supply = <®_1p8v>; ++ clocks = <&sys_mclk>; ++ }; ++}; ++ ++&qspi { ++ num-cs = <1>; ++ bus-num = <0>; ++ status = "okay"; ++ ++ qflash0: w25q16dw@0 { ++ compatible = "spansion,m25p80"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ m25p,fast-read; ++ spi-max-frequency = <20000000>; ++ reg = <0>; ++ }; ++}; ++ ++&pfe { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ ethernet@0 { ++ compatible = "fsl,pfe-gemac-port"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x0>; /* GEM_ID */ ++ fsl,gemac-bus-id = <0x0>; /* BUS_ID */ ++ fsl,gemac-phy-id = <0x2>; /* PHY_ID */ ++ fsl,mdio-mux-val = <0x0>; ++ phy-mode = "sgmii"; ++ fsl,pfe-phy-if-flags = <0x0>; ++ ++ mdio@0 { ++ reg = <0x1>; /* enabled/disabled */ ++ }; ++ }; ++ ++ ethernet@1 { ++ compatible = "fsl,pfe-gemac-port"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x1>; /* GEM_ID */ ++ fsl,gemac-bus-id = <0x1>; /* BUS_ID */ ++ fsl,gemac-phy-id = <0x1>; /* PHY_ID */ ++ fsl,mdio-mux-val = <0x0>; ++ phy-mode = "sgmii"; ++ fsl,pfe-phy-if-flags = <0x0>; ++ ++ mdio@0 { ++ reg = <0x0>; /* enabled/disabled */ ++ }; ++ }; ++}; ++ ++&sai2 { ++ status = "okay"; ++}; +--- /dev/null ++++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts +@@ -0,0 +1,166 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Device Tree file for Freescale LS1012A QDS Board. ++ * ++ * Copyright 2016 Freescale Semiconductor, Inc. ++ * ++ */ ++/dts-v1/; ++ ++#include "fsl-ls1012a.dtsi" ++ ++/ { + model = "LS1012A QDS Board"; + compatible = "fsl,ls1012a-qds", "fsl,ls1012a"; + @@ -1335,49 +1565,13 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts -@@ -0,0 +1,138 @@ +@@ -0,0 +1,102 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Device Tree file for Freescale LS1012A RDB Board. + * + * Copyright 2016 Freescale Semiconductor, Inc. + * -+ * 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/; + @@ -1476,49 +1670,13 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi -@@ -0,0 +1,602 @@ +@@ -0,0 +1,567 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Device Tree Include file for Freescale Layerscape-1012A family SoC. + * + * Copyright 2016 Freescale Semiconductor, Inc. + * -+ * 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. + */ + +#include <dt-bindings/interrupt-controller/arm-gic.h> @@ -1854,12 +2012,13 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + }; + + i2c0: i2c@2180000 { -+ compatible = "fsl,vf610-i2c"; ++ compatible = "fsl,vf610-i2c", "fsl,ls1012a-vf610-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x2180000 0x0 0x10000>; + interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clockgen 4 3>; ++ fsl-scl-gpio = <&gpio0 13 0>; + status = "disabled"; + }; + @@ -2081,13 +2240,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043-post.dtsi -@@ -0,0 +1,45 @@ +@@ -0,0 +1,44 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * QorIQ FMan v3 device tree nodes for ls1043 + * + * Copyright 2015-2016 Freescale Semiconductor Inc. -+ * -+ * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + */ + +&soc { @@ -2129,7 +2287,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds-sdk.dts -@@ -0,0 +1,69 @@ +@@ -0,0 +1,71 @@ +/* + * Device Tree Include file for Freescale Layerscape-1043A family SoC. + * @@ -2177,6 +2335,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + */ + +#include "fsl-ls1043a-qds.dts" ++#include "qoriq-qman-portals-sdk.dtsi" ++#include "qoriq-bman-portals-sdk.dtsi" + +&bman_fbpr { + compatible = "fsl,bman-fbpr"; @@ -2201,7 +2361,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; --- a/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts -@@ -1,7 +1,7 @@ +@@ -1,51 +1,14 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Device Tree Include file for Freescale Layerscape-1043A family SoC. * @@ -2209,8 +2370,44 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * Copyright 2014-2015 Freescale Semiconductor, Inc. * * Mingkai Hu <Mingkai.hu@freescale.com> - * -@@ -45,7 +45,7 @@ +- * +- * 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/; @@ -2219,7 +2416,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> / { model = "LS1043A QDS Board"; -@@ -60,6 +60,22 @@ +@@ -60,6 +23,22 @@ serial1 = &duart1; serial2 = &duart2; serial3 = &duart3; @@ -2242,7 +2439,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }; chosen { -@@ -97,8 +113,11 @@ +@@ -97,8 +76,11 @@ }; fpga: board-control@2,0 { @@ -2255,7 +2452,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }; }; -@@ -181,3 +200,149 @@ +@@ -181,3 +163,149 @@ reg = <0>; }; }; @@ -2407,7 +2604,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb-sdk.dts -@@ -0,0 +1,69 @@ +@@ -0,0 +1,71 @@ +/* + * Device Tree Include file for Freescale Layerscape-1043A family SoC. + * @@ -2455,6 +2652,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + */ + +#include "fsl-ls1043a-rdb.dts" ++#include "qoriq-qman-portals-sdk.dtsi" ++#include "qoriq-bman-portals-sdk.dtsi" + +&bman_fbpr { + compatible = "fsl,bman-fbpr"; @@ -2599,7 +2798,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; --- a/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts -@@ -1,7 +1,7 @@ +@@ -1,51 +1,14 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Device Tree Include file for Freescale Layerscape-1043A family SoC. * @@ -2607,8 +2807,44 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * Copyright 2014-2015 Freescale Semiconductor, Inc. * * Mingkai Hu <Mingkai.hu@freescale.com> - * -@@ -45,7 +45,7 @@ +- * +- * 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/; @@ -2617,7 +2853,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> / { model = "LS1043A RDB Board"; -@@ -86,6 +86,10 @@ +@@ -86,6 +49,10 @@ compatible = "pericom,pt7c4338"; reg = <0x68>; }; @@ -2628,7 +2864,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }; &ifc { -@@ -130,6 +134,38 @@ +@@ -130,6 +97,38 @@ reg = <0>; spi-max-frequency = <1000000>; /* input clock */ }; @@ -2667,7 +2903,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }; &duart0 { -@@ -139,3 +175,76 @@ +@@ -139,3 +138,76 @@ &duart1 { status = "okay"; }; @@ -2746,7 +2982,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; --- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi -@@ -1,7 +1,7 @@ +@@ -1,55 +1,32 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Device Tree Include file for Freescale Layerscape-1043A family SoC. * @@ -2754,12 +2991,48 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * Copyright 2014-2015 Freescale Semiconductor, Inc. * * Mingkai Hu <Mingkai.hu@freescale.com> - * -@@ -44,12 +44,25 @@ - * OTHER DEALINGS IN THE SOFTWARE. +- * +- * 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. */ +#include <dt-bindings/thermal/thermal.h> ++#include <dt-bindings/interrupt-controller/arm-gic.h> + / { compatible = "fsl,ls1043a"; @@ -2781,7 +3054,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> cpus { #address-cells = <1>; #size-cells = <0>; -@@ -66,6 +79,8 @@ +@@ -66,6 +43,8 @@ reg = <0x0>; clocks = <&clockgen 1 0>; next-level-cache = <&l2>; @@ -2790,7 +3063,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }; cpu1: cpu@1 { -@@ -74,6 +89,7 @@ +@@ -74,6 +53,7 @@ reg = <0x1>; clocks = <&clockgen 1 0>; next-level-cache = <&l2>; @@ -2798,7 +3071,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }; cpu2: cpu@2 { -@@ -82,6 +98,7 @@ +@@ -82,6 +62,7 @@ reg = <0x2>; clocks = <&clockgen 1 0>; next-level-cache = <&l2>; @@ -2806,7 +3079,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }; cpu3: cpu@3 { -@@ -90,6 +107,7 @@ +@@ -90,6 +71,7 @@ reg = <0x3>; clocks = <&clockgen 1 0>; next-level-cache = <&l2>; @@ -2814,7 +3087,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }; l2: l2-cache { -@@ -97,12 +115,56 @@ +@@ -97,12 +79,56 @@ }; }; @@ -2871,7 +3144,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> sysclk: sysclk { compatible = "fixed-clock"; #clock-cells = <0>; -@@ -149,7 +211,7 @@ +@@ -149,7 +175,7 @@ interrupts = <1 9 0xf08>; }; @@ -2880,7 +3153,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> compatible = "simple-bus"; #address-cells = <2>; #size-cells = <2>; -@@ -213,13 +275,14 @@ +@@ -213,13 +239,14 @@ dcfg: dcfg@1ee0000 { compatible = "fsl,ls1043a-dcfg", "syscon"; @@ -2896,7 +3169,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> interrupts = <0 43 0x4>; }; -@@ -255,6 +318,103 @@ +@@ -255,6 +282,103 @@ big-endian; }; @@ -3000,7 +3273,24 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> dspi0: dspi@2100000 { compatible = "fsl,ls1043a-dspi", "fsl,ls1021a-v1.0-dspi"; #address-cells = <1>; -@@ -396,6 +556,72 @@ +@@ -282,7 +406,7 @@ + }; + + i2c0: i2c@2180000 { +- compatible = "fsl,vf610-i2c"; ++ compatible = "fsl,vf610-i2c", "fsl,ls1043a-vf610-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x2180000 0x0 0x10000>; +@@ -292,6 +416,7 @@ + dmas = <&edma0 1 39>, + <&edma0 1 38>; + dma-names = "tx", "rx"; ++ fsl-scl-gpio = <&gpio4 12 0>; + status = "disabled"; + }; + +@@ -396,6 +521,72 @@ #interrupt-cells = <2>; }; @@ -3073,7 +3363,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> lpuart0: serial@2950000 { compatible = "fsl,ls1021a-lpuart"; reg = <0x0 0x2950000 0x0 0x1000>; -@@ -450,6 +676,16 @@ +@@ -450,6 +641,16 @@ status = "disabled"; }; @@ -3090,32 +3380,38 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> wdog0: wdog@2ad0000 { compatible = "fsl,ls1043a-wdt", "fsl,imx21-wdt"; reg = <0x0 0x2ad0000 0x0 0x10000>; -@@ -482,6 +718,8 @@ +@@ -482,6 +683,10 @@ dr_mode = "host"; snps,quirk-frame-length-adjustment = <0x20>; snps,dis_rxdet_inp3_quirk; + snps,incr-burst-type-adjustment = <1>, <4>, <8>, <16>; + snps,dma-snooping; ++ usb3-lpm-capable; ++ snps,dis-u1u2-when-u3-quirk; }; usb1: usb3@3000000 { -@@ -491,6 +729,9 @@ +@@ -491,6 +696,11 @@ dr_mode = "host"; snps,quirk-frame-length-adjustment = <0x20>; snps,dis_rxdet_inp3_quirk; + snps,incr-burst-type-adjustment = <1>, <4>, <8>, <16>; + snps,dma-snooping; + configure-gfladj; ++ usb3-lpm-capable; ++ snps,dis-u1u2-when-u3-quirk; }; usb2: usb3@3100000 { -@@ -500,32 +741,52 @@ +@@ -500,32 +710,54 @@ dr_mode = "host"; snps,quirk-frame-length-adjustment = <0x20>; snps,dis_rxdet_inp3_quirk; + snps,incr-burst-type-adjustment = <1>, <4>, <8>, <16>; + snps,dma-snooping; + configure-gfladj; ++ usb3-lpm-capable; ++ snps,dis-u1u2-when-u3-quirk; }; sata: sata@3200000 { @@ -3166,7 +3462,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> reg = <0x0 0x1573000 0x0 0x8>; msi-controller; interrupts = <0 160 0x4>; -@@ -536,9 +797,9 @@ +@@ -536,9 +768,9 @@ reg = <0x00 0x03400000 0x0 0x00100000 /* controller registers */ 0x40 0x00000000 0x0 0x00002000>; /* configuration space */ reg-names = "regs", "config"; @@ -3179,7 +3475,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> #address-cells = <3>; #size-cells = <2>; device_type = "pci"; -@@ -547,7 +808,7 @@ +@@ -547,7 +779,7 @@ 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 */ @@ -3188,7 +3484,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic 0 110 0x4>, -@@ -561,9 +822,9 @@ +@@ -561,9 +793,9 @@ reg = <0x00 0x03500000 0x0 0x00100000 /* controller registers */ 0x48 0x00000000 0x0 0x00002000>; /* configuration space */ reg-names = "regs", "config"; @@ -3201,7 +3497,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> #address-cells = <3>; #size-cells = <2>; device_type = "pci"; -@@ -572,7 +833,7 @@ +@@ -572,7 +804,7 @@ 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 */ @@ -3210,7 +3506,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic 0 120 0x4>, -@@ -586,9 +847,9 @@ +@@ -586,9 +818,9 @@ reg = <0x00 0x03600000 0x0 0x00100000 /* controller registers */ 0x50 0x00000000 0x0 0x00002000>; /* configuration space */ reg-names = "regs", "config"; @@ -3223,7 +3519,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> #address-cells = <3>; #size-cells = <2>; device_type = "pci"; -@@ -597,7 +858,7 @@ +@@ -597,7 +829,7 @@ 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 */ @@ -3232,7 +3528,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic 0 154 0x4>, -@@ -607,4 +868,13 @@ +@@ -607,4 +839,13 @@ }; }; @@ -3244,17 +3540,17 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + }; }; + -+#include "qoriq-qman1-portals.dtsi" -+#include "qoriq-bman1-portals.dtsi" ++#include "qoriq-qman-portals.dtsi" ++#include "qoriq-bman-portals.dtsi" --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls1046-post.dtsi @@ -0,0 +1,48 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * QorIQ FMan v3 device tree nodes for ls1046 + * + * Copyright 2015-2016 Freescale Semiconductor Inc. + * -+ * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + */ + +&soc { @@ -3299,7 +3595,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds-sdk.dts -@@ -0,0 +1,110 @@ +@@ -0,0 +1,112 @@ +/* + * Device Tree Include file for Freescale Layerscape-1046A family SoC. + * @@ -3347,6 +3643,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + */ + +#include "fsl-ls1046a-qds.dts" ++#include "qoriq-qman-portals-sdk.dtsi" ++#include "qoriq-bman-portals-sdk.dtsi" + +&bman_fbpr { + compatible = "fsl,bman-fbpr"; @@ -3412,51 +3710,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts -@@ -0,0 +1,363 @@ +@@ -0,0 +1,326 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Device Tree Include file for Freescale Layerscape-1046A family SoC. + * + * Copyright 2016 Freescale Semiconductor, Inc. + * + * Shaohui Xie <Shaohui.Xie@nxp.com> -+ * -+ * 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/; @@ -3778,7 +4039,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb-sdk.dts -@@ -0,0 +1,83 @@ +@@ -0,0 +1,85 @@ +/* + * Device Tree Include file for Freescale Layerscape-1046A family SoC. + * @@ -3826,6 +4087,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + */ + +#include "fsl-ls1046a-rdb.dts" ++#include "qoriq-qman-portals-sdk.dtsi" ++#include "qoriq-bman-portals-sdk.dtsi" + +&bman_fbpr { + compatible = "fsl,bman-fbpr"; @@ -3977,51 +4240,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts -@@ -0,0 +1,218 @@ +@@ -0,0 +1,181 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Device Tree Include file for Freescale Layerscape-1046A family SoC. + * + * Copyright 2016 Freescale Semiconductor, Inc. + * + * Mingkai Hu <mingkai.hu@nxp.com> -+ * -+ * 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/; @@ -4198,51 +4424,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi -@@ -0,0 +1,800 @@ +@@ -0,0 +1,771 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Device Tree Include file for Freescale Layerscape-1046A family SoC. + * + * Copyright 2016 Freescale Semiconductor, Inc. + * + * Mingkai Hu <mingkai.hu@nxp.com> -+ * -+ * 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. + */ + +#include <dt-bindings/interrupt-controller/arm-gic.h> @@ -4608,7 +4797,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + }; + + i2c0: i2c@2180000 { -+ compatible = "fsl,vf610-i2c"; ++ compatible = "fsl,vf610-i2c", "fsl,ls1046a-vf610-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x2180000 0x0 0x10000>; @@ -4617,6 +4806,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + dmas = <&edma0 1 39>, + <&edma0 1 38>; + dma-names = "tx", "rx"; ++ fsl-scl-gpio = <&gpio3 12 0>; + status = "disabled"; + }; + @@ -4641,12 +4831,13 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + }; + + i2c3: i2c@21b0000 { -+ compatible = "fsl,vf610-i2c"; ++ compatible = "fsl,vf610-i2c", "fsl,ls1046a-vf610-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x21b0000 0x0 0x10000>; + interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clockgen 4 1>; ++ fsl-scl-gpio = <&gpio3 12 0>; + status = "disabled"; + }; + @@ -4812,6 +5003,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + dr_mode = "host"; + snps,quirk-frame-length-adjustment = <0x20>; + snps,dis_rxdet_inp3_quirk; ++ usb3-lpm-capable; ++ snps,dis-u1u2-when-u3-quirk; + }; + + usb1: usb@3000000 { @@ -4821,6 +5014,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + dr_mode = "host"; + snps,quirk-frame-length-adjustment = <0x20>; + snps,dis_rxdet_inp3_quirk; ++ usb3-lpm-capable; ++ snps,dis-u1u2-when-u3-quirk; + }; + + usb2: usb@3100000 { @@ -4830,6 +5025,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + dr_mode = "host"; + snps,quirk-frame-length-adjustment = <0x20>; + snps,dis_rxdet_inp3_quirk; ++ usb3-lpm-capable; ++ snps,dis-u1u2-when-u3-quirk; + }; + + sata: sata@3200000 { @@ -4997,11 +5194,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + }; +}; + -+#include "qoriq-qman1-portals.dtsi" -+#include "qoriq-bman1-portals.dtsi" ++#include "qoriq-qman-portals.dtsi" ++#include "qoriq-bman-portals.dtsi" --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts -@@ -0,0 +1,173 @@ +@@ -0,0 +1,137 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Device Tree file for NXP LS1088A QDS Board. + * @@ -5009,43 +5207,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * + * Harninder Rai <harninder.rai@nxp.com> + * -+ * 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/; @@ -5177,7 +5338,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts -@@ -0,0 +1,236 @@ +@@ -0,0 +1,200 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Device Tree file for NXP LS1088A RDB Board. + * @@ -5185,43 +5347,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * + * Harninder Rai <harninder.rai@nxp.com> + * -+ * 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/; @@ -5416,7 +5541,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi -@@ -0,0 +1,825 @@ +@@ -0,0 +1,800 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Device Tree Include file for NXP Layerscape-1088A family SoC. + * @@ -5424,43 +5550,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * + * Harninder Rai <harninder.rai@nxp.com> + * -+ * 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. + */ +#include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/thermal/thermal.h> @@ -5593,70 +5682,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + <1 10 IRQ_TYPE_LEVEL_LOW>;/* Hypervisor PPI */ + }; + -+ fsl_mc: fsl-mc@80c000000 { -+ compatible = "fsl,qoriq-mc"; -+ reg = <0x00000008 0x0c000000 0 0x40>, /* MC portal base */ -+ <0x00000000 0x08340000 0 0x40000>; /* MC control reg */ -+ msi-parent = <&its>; -+ iommu-map = <0 &smmu 0 0>; /* This is fixed-up by u-boot */ -+ #address-cells = <3>; -+ #size-cells = <1>; -+ -+ /* -+ * Region type 0x0 - MC portals -+ * Region type 0x1 - QBMAN portals -+ */ -+ ranges = <0x0 0x0 0x0 0x8 0x0c000000 0x4000000 -+ 0x1 0x0 0x0 0x8 0x18000000 0x8000000>; -+ -+ dpmacs { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ dpmac1: dpmac@1 { -+ compatible = "fsl,qoriq-mc-dpmac"; -+ reg = <1>; -+ }; -+ dpmac2: dpmac@2 { -+ compatible = "fsl,qoriq-mc-dpmac"; -+ reg = <2>; -+ }; -+ dpmac3: dpmac@3 { -+ compatible = "fsl,qoriq-mc-dpmac"; -+ reg = <3>; -+ }; -+ dpmac4: dpmac@4 { -+ compatible = "fsl,qoriq-mc-dpmac"; -+ reg = <4>; -+ }; -+ dpmac5: dpmac@5 { -+ compatible = "fsl,qoriq-mc-dpmac"; -+ reg = <5>; -+ }; -+ dpmac6: dpmac@6 { -+ compatible = "fsl,qoriq-mc-dpmac"; -+ reg = <6>; -+ }; -+ dpmac7: dpmac@7 { -+ compatible = "fsl,qoriq-mc-dpmac"; -+ reg = <7>; -+ }; -+ dpmac8: dpmac@8 { -+ compatible = "fsl,qoriq-mc-dpmac"; -+ reg = <8>; -+ }; -+ dpmac9: dpmac@9 { -+ compatible = "fsl,qoriq-mc-dpmac"; -+ reg = <9>; -+ }; -+ dpmac10: dpmac@10 { -+ compatible = "fsl,qoriq-mc-dpmac"; -+ reg = <0xa>; -+ }; -+ }; -+ -+ }; -+ + sysclk: sysclk { + compatible = "fixed-clock"; + #clock-cells = <0>; @@ -5688,6 +5713,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + #address-cells = <2>; + #size-cells = <2>; + ranges; ++ dma-ranges = <0x0 0x0 0x0 0x0 0x10000 0x00000000>; + + clockgen: clocking@1300000 { + compatible = "fsl,ls1088a-clockgen"; @@ -5937,12 +5963,13 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + }; + + i2c0: i2c@2000000 { -+ compatible = "fsl,vf610-i2c"; ++ compatible = "fsl,vf610-i2c", "fsl,ls1088a-vf610-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x2000000 0x0 0x10000>; + interrupts = <0 34 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clockgen 4 7>; ++ fsl-scl-gpio = <&gpio3 30 0>; + status = "disabled"; + }; + @@ -6108,6 +6135,79 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + <0000 0 0 4 &gic 0 0 0 122 IRQ_TYPE_LEVEL_HIGH>; + }; + ++ fsl_mc: fsl-mc@80c000000 { ++ compatible = "fsl,qoriq-mc"; ++ reg = <0x00000008 0x0c000000 0 0x40>, /* MC portal base */ ++ <0x00000000 0x08340000 0 0x40000>; /* MC control reg */ ++ msi-parent = <&its>; ++ iommu-map = <0 &smmu 0 0>; /* This is fixed-up by u-boot */ ++ dma-coherent; ++ #address-cells = <3>; ++ #size-cells = <1>; ++ ++ /* ++ * Region type 0x0 - MC portals ++ * Region type 0x1 - QBMAN portals ++ */ ++ ranges = <0x0 0x0 0x0 0x8 0x0c000000 0x4000000 ++ 0x1 0x0 0x0 0x8 0x18000000 0x8000000>; ++ ++ dpmacs { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ dpmac1: dpmac@1 { ++ compatible = "fsl,qoriq-mc-dpmac"; ++ reg = <1>; ++ }; ++ ++ dpmac2: dpmac@2 { ++ compatible = "fsl,qoriq-mc-dpmac"; ++ reg = <2>; ++ }; ++ ++ dpmac3: dpmac@3 { ++ compatible = "fsl,qoriq-mc-dpmac"; ++ reg = <3>; ++ }; ++ ++ dpmac4: dpmac@4 { ++ compatible = "fsl,qoriq-mc-dpmac"; ++ reg = <4>; ++ }; ++ ++ dpmac5: dpmac@5 { ++ compatible = "fsl,qoriq-mc-dpmac"; ++ reg = <5>; ++ }; ++ ++ dpmac6: dpmac@6 { ++ compatible = "fsl,qoriq-mc-dpmac"; ++ reg = <6>; ++ }; ++ ++ dpmac7: dpmac@7 { ++ compatible = "fsl,qoriq-mc-dpmac"; ++ reg = <7>; ++ }; ++ ++ dpmac8: dpmac@8 { ++ compatible = "fsl,qoriq-mc-dpmac"; ++ reg = <8>; ++ }; ++ ++ dpmac9: dpmac@9 { ++ compatible = "fsl,qoriq-mc-dpmac"; ++ reg = <9>; ++ }; ++ ++ dpmac10: dpmac@a { ++ compatible = "fsl,qoriq-mc-dpmac"; ++ reg = <0xa>; ++ }; ++ }; ++ }; ++ + smmu: iommu@5000000 { + compatible = "arm,mmu-500"; + reg = <0 0x5000000 0 0x800000>; @@ -6244,7 +6344,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; --- a/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts -@@ -1,8 +1,10 @@ +@@ -1,214 +1,87 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Device Tree file for Freescale LS2080a QDS Board. * @@ -6255,8 +6356,44 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * Abhimanyu Saini <abhimanyu.saini@nxp.com> * Bhupesh Sharma <bhupesh.sharma@freescale.com> * - * This file is dual-licensed: you can use it either under the terms -@@ -46,169 +48,76 @@ +- * 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/; @@ -6299,19 +6436,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - bank-width = <2>; - device-width = <1>; - }; -+ compatible = "fsl,tetra-fpga", "fsl,fpga-qixis", "simple-bus"; -+ reg = <3 0 0x300>; /* TODO check address */ -+ ranges = <0 3 0 0x300>; - +- - nand@2,0 { - compatible = "fsl,ifc-nand"; - reg = <0x2 0x0 0x10000>; - }; -+ mdio_mux_emi1 { -+ compatible = "mdio-mux-mmioreg", "mdio-mux"; -+ mdio-parent-bus = <&emdio1>; -+ reg = <0x54 1>; /* BRDCFG4 */ -+ mux-mask = <0xe0>; /* EMI1_MDIO */ ++ compatible = "fsl,tetra-fpga", "fsl,fpga-qixis", "simple-bus"; ++ reg = <3 0 0x300>; /* TODO check address */ ++ ranges = <0 3 0 0x300>; - cpld@3,0 { - reg = <0x3 0x0 0x10000>; @@ -6328,15 +6460,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - #size-cells = <0>; - i2c@0 { - #address-cells = <1>; -+ #address-cells=<1>; - #size-cells = <0>; +- #size-cells = <0>; - reg = <0x00>; - rtc@68 { - compatible = "dallas,ds3232"; - reg = <0x68>; - }; - }; - +- - i2c@2 { - #address-cells = <1>; - #size-cells = <0>; @@ -6354,12 +6485,18 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - shunt-resistor = <1000>; - }; - }; -- ++ mdio_mux_emi1 { ++ compatible = "mdio-mux-mmioreg", "mdio-mux"; ++ mdio-parent-bus = <&emdio1>; ++ reg = <0x54 1>; /* BRDCFG4 */ ++ mux-mask = <0xe0>; /* EMI1_MDIO */ + - i2c@3 { - #address-cells = <1>; -- #size-cells = <0>; ++ #address-cells=<1>; + #size-cells = <0>; - reg = <0x3>; -- + - adt7481@4c { - compatible = "adi,adt7461"; - reg = <0x4c>; @@ -6396,7 +6533,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> -&i2c1 { - status = "disabled"; --}; ++/* Update DPMAC connections to external PHYs, under SerDes 0x2a_0x49. */ ++&dpmac9 { ++ phy-handle = <&mdio0_phy12>; + }; - -&i2c2 { - status = "disabled"; @@ -6429,7 +6569,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - spi-max-frequency = <3000000>; - reg = <2>; - }; --}; ++&dpmac10 { ++ phy-handle = <&mdio0_phy13>; + }; - -&qspi { - status = "okay"; @@ -6447,26 +6589,21 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - spi-max-frequency = <20000000>; - reg = <0>; - }; --}; ++&dpmac11 { ++ phy-handle = <&mdio0_phy14>; + }; - -&sata0 { - status = "okay"; -+/* Update DPMAC connections to external PHYs, under SerDes 0x2a_0x49. */ -+&dpmac9 { -+ phy-handle = <&mdio0_phy12>; - }; +-}; - -&sata1 { - status = "okay"; -+&dpmac10 { -+ phy-handle = <&mdio0_phy13>; - }; +-}; - -&usb0 { - status = "okay"; -+&dpmac11 { -+ phy-handle = <&mdio0_phy14>; - }; +-}; - -&usb1 { - status = "okay"; @@ -6475,7 +6612,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }; --- a/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts -@@ -1,8 +1,10 @@ +@@ -1,170 +1,105 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Device Tree file for Freescale LS2080a RDB Board. * @@ -6486,8 +6624,44 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * Abhimanyu Saini <abhimanyu.saini@nxp.com> * Bhupesh Sharma <bhupesh.sharma@freescale.com> * - * This file is dual-licensed: you can use it either under the terms -@@ -46,125 +48,94 @@ +- * 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/; @@ -6685,7 +6859,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }; --- a/arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts -@@ -1,7 +1,7 @@ +@@ -1,62 +1,21 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Device Tree file for Freescale LS2080a software Simulator model * @@ -6694,7 +6869,44 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> * * Bhupesh Sharma <bhupesh.sharma@freescale.com> * -@@ -46,17 +46,12 @@ +- * This file is dual-licensed: you can use it either under the terms +- * of the GPL 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/; @@ -6715,7 +6927,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> reg = <0x0 0x2210000 0x0 0x100>; --- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi -@@ -1,8 +1,9 @@ +@@ -1,739 +1,144 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Device Tree Include file for Freescale Layerscape-2080A family SoC. * @@ -6725,9 +6938,43 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * Abhimanyu Saini <abhimanyu.saini@nxp.com> * Bhupesh Sharma <bhupesh.sharma@freescale.com> * - * This file is dual-licensed: you can use it either under the terms -@@ -44,696 +45,132 @@ - * OTHER DEALINGS IN THE SOFTWARE. +- * 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. */ -/ { @@ -7519,6 +7766,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + snps,dma-snooping; +}; + ++&timer { ++ fsl,erratum-a008585; ++}; ++ +&pcie1 { + reg = <0x00 0x03400000 0x0 0x00100000 /* controller registers */ + 0x10 0x00000000 0x0 0x00002000>; /* configuration space */ @@ -7716,7 +7967,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls2088a-qds.dts -@@ -0,0 +1,162 @@ +@@ -0,0 +1,126 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Device Tree file for Freescale LS2088A QDS Board. + * @@ -7725,43 +7977,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * + * Abhimanyu Saini <abhimanyu.saini@nxp.com> + * -+ * 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/; @@ -7881,7 +8096,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls2088a-rdb.dts -@@ -0,0 +1,140 @@ +@@ -0,0 +1,104 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Device Tree file for Freescale LS2088A RDB Board. + * @@ -7890,43 +8106,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * + * Abhimanyu Saini <abhimanyu.saini@nxp.com> + * -+ * 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/; @@ -8024,7 +8203,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi -@@ -0,0 +1,195 @@ +@@ -0,0 +1,159 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Device Tree Include file for Freescale Layerscape-2088A family SoC. + * @@ -8033,43 +8213,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * + * Abhimanyu Saini <abhimanyu.saini@nxp.com> + * -+ * 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. + */ + +#include "fsl-ls208xa.dtsi" @@ -8222,7 +8365,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls208xa-qds.dtsi -@@ -0,0 +1,198 @@ +@@ -0,0 +1,162 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Device Tree file for Freescale LS2080A QDS Board. + * @@ -8231,43 +8375,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * + * Abhimanyu Saini <abhimanyu.saini@nxp.com> + * -+ * 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. + */ + +&esdhc { @@ -8423,7 +8530,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi -@@ -0,0 +1,161 @@ +@@ -0,0 +1,136 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Device Tree file for Freescale LS2080A RDB Board. + * @@ -8432,43 +8540,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * + * Abhimanyu Saini <abhimanyu.saini@nxp.com> + * -+ * 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. + */ + +&esdhc { @@ -8522,6 +8593,17 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + }; + }; + ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x02>; ++ ina220@40 { ++ compatible = "ti,ina220"; ++ reg = <0x40>; ++ shunt-resistor = <500>; ++ }; ++ }; ++ + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; @@ -8587,7 +8669,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi -@@ -0,0 +1,919 @@ +@@ -0,0 +1,885 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Device Tree Include file for Freescale Layerscape-2080A family SoC. + * @@ -8596,43 +8679,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * + * Abhimanyu Saini <abhimanyu.saini@nxp.com> + * -+ * 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. + */ + +#include <dt-bindings/thermal/thermal.h> @@ -8701,13 +8747,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + mask = <0x2>; + }; + -+ timer { ++ timer: timer { + compatible = "arm,armv8-timer"; + interrupts = <1 13 4>, /* Physical Secure PPI, active-low */ + <1 14 4>, /* Physical Non-Secure PPI, active-low */ + <1 11 4>, /* Virtual PPI, active-low */ + <1 10 4>; /* Hypervisor PPI, active-low */ -+ fsl,erratum-a008585; + }; + + pmu { @@ -8720,6 +8765,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + #address-cells = <2>; + #size-cells = <2>; + ranges; ++ dma-ranges = <0x0 0x0 0x0 0x0 0x10000 0x00000000>; + + clockgen: clocking@1300000 { + compatible = "fsl,ls2080a-clockgen"; @@ -8943,6 +8989,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + <0x00000000 0x08340000 0 0x40000>; /* MC control reg */ + msi-parent = <&its>; + iommu-map = <0 &smmu 0 0>; /* This is fixed-up by u-boot */ ++ dma-coherent; + #address-cells = <3>; + #size-cells = <1>; + @@ -9273,13 +9320,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + i2c0: i2c@2000000 { + status = "disabled"; -+ compatible = "fsl,vf610-i2c"; ++ compatible = "fsl,vf610-i2c", "fsl,ls208xa-vf610-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x2000000 0x0 0x10000>; + interrupts = <0 34 0x4>; /* Level high type */ + clock-names = "i2c"; + clocks = <&clockgen 4 1>; ++ fsl-scl-gpio = <&gpio3 10 0>; + }; + + i2c1: i2c@2010000 { @@ -9508,87 +9556,141 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + }; +}; --- /dev/null -+++ b/arch/arm64/boot/dts/freescale/qoriq-bman1-portals.dtsi -@@ -0,0 +1,81 @@ ++++ b/arch/arm64/boot/dts/freescale/qoriq-bman-portals-sdk.dtsi +@@ -0,0 +1,55 @@ +/* -+ * QorIQ BMan Portals device tree ++ * QorIQ BMan SDK Portals device tree nodes + * + * Copyright 2011-2016 Freescale Semiconductor Inc. ++ * Copyright 2017 NXP + * + * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + */ + +&bportals { ++ bman-portal@0 { ++ cell-index = <0>; ++ }; ++ ++ bman-portal@10000 { ++ cell-index = <1>; ++ }; ++ ++ bman-portal@20000 { ++ cell-index = <2>; ++ }; ++ ++ bman-portal@30000 { ++ cell-index = <3>; ++ }; ++ ++ bman-portal@40000 { ++ cell-index = <4>; ++ }; ++ ++ bman-portal@50000 { ++ cell-index = <5>; ++ }; ++ ++ bman-portal@60000 { ++ cell-index = <6>; ++ }; ++ ++ bman-portal@70000 { ++ cell-index = <7>; ++ }; ++ ++ bman-portal@80000 { ++ cell-index = <8>; ++ }; ++ ++ bman-portal@90000 { ++ cell-index = <9>; ++ }; ++ ++ bman-bpids@0 { ++ compatible = "fsl,bpid-range"; ++ fsl,bpid-range = <32 32>; ++ }; ++}; +--- /dev/null ++++ b/arch/arm64/boot/dts/freescale/qoriq-bman-portals.dtsi +@@ -0,0 +1,77 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * QorIQ BMan Portals device tree ++ * ++ * Copyright 2011-2016 Freescale Semiconductor Inc. ++ * ++ */ ++ ++&bportals { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + + bman-portal@0 { -+ cell-index = <0>; ++ /* ++ * bootloader fix-ups are expected to provide the ++ * "fsl,bman-portal-<hardware revision>" compatible ++ */ + compatible = "fsl,bman-portal"; -+ reg = <0x0 0x4000 0x4000000 0x4000>; -+ interrupts = <0 173 0x4>; ++ reg = <0x0 0x4000>, <0x4000000 0x4000>; ++ interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>; + }; + + bman-portal@10000 { -+ cell-index = <1>; + compatible = "fsl,bman-portal"; -+ reg = <0x10000 0x4000 0x4010000 0x4000>; -+ interrupts = <0 175 0x4>; ++ reg = <0x10000 0x4000>, <0x4010000 0x4000>; ++ interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>; + }; + + bman-portal@20000 { -+ cell-index = <2>; + compatible = "fsl,bman-portal"; -+ reg = <0x20000 0x4000 0x4020000 0x4000>; -+ interrupts = <0 177 0x4>; ++ reg = <0x20000 0x4000>, <0x4020000 0x4000>; ++ interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>; + }; + + bman-portal@30000 { -+ cell-index = <3>; + compatible = "fsl,bman-portal"; -+ reg = <0x30000 0x4000 0x4030000 0x4000>; -+ interrupts = <0 179 0x4>; ++ reg = <0x30000 0x4000>, <0x4030000 0x4000>; ++ interrupts = <GIC_SPI 179 IRQ_TYPE_LEVEL_HIGH>; + }; + + bman-portal@40000 { -+ cell-index = <4>; + compatible = "fsl,bman-portal"; -+ reg = <0x40000 0x4000 0x4040000 0x4000>; -+ interrupts = <0 181 0x4>; ++ reg = <0x40000 0x4000>, <0x4040000 0x4000>; ++ interrupts = <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>; + }; + + bman-portal@50000 { -+ cell-index = <5>; + compatible = "fsl,bman-portal"; -+ reg = <0x50000 0x4000 0x4050000 0x4000>; -+ interrupts = <0 183 0x4>; ++ reg = <0x50000 0x4000>, <0x4050000 0x4000>; ++ interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>; + }; + + bman-portal@60000 { -+ cell-index = <6>; + compatible = "fsl,bman-portal"; -+ reg = <0x60000 0x4000 0x4060000 0x4000>; -+ interrupts = <0 185 0x4>; ++ reg = <0x60000 0x4000>, <0x4060000 0x4000>; ++ interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>; + }; + + bman-portal@70000 { -+ cell-index = <7>; + compatible = "fsl,bman-portal"; -+ reg = <0x70000 0x4000 0x4070000 0x4000>; -+ interrupts = <0 187 0x4>; ++ reg = <0x70000 0x4000>, <0x4070000 0x4000>; ++ interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>; + }; + + bman-portal@80000 { -+ cell-index = <8>; + compatible = "fsl,bman-portal"; -+ reg = <0x80000 0x4000 0x4080000 0x4000>; -+ interrupts = <0 189 0x4>; ++ reg = <0x80000 0x4000>, <0x4080000 0x4000>; ++ interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>; + }; + -+ bman-bpids@0 { -+ compatible = "fsl,bpid-range"; -+ fsl,bpid-range = <32 32>; ++ bman-portal@90000 { ++ compatible = "fsl,bman-portal"; ++ reg = <0x90000 0x4000>, <0x4090000 0x4000>; ++ interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>; + }; +}; --- /dev/null @@ -9670,12 +9772,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- /dev/null +++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-0.dtsi @@ -0,0 +1,43 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * QorIQ FMan v3 10g port #0 device tree + * + * Copyright 2012-2015 Freescale Semiconductor Inc. + * -+ * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + */ + +fman@1a00000 { @@ -9716,12 +9818,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- /dev/null +++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-1.dtsi @@ -0,0 +1,43 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * QorIQ FMan v3 10g port #1 device tree + * + * Copyright 2012-2015 Freescale Semiconductor Inc. + * -+ * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + */ + +fman@1a00000 { @@ -9762,12 +9864,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- /dev/null +++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-0.dtsi @@ -0,0 +1,42 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * QorIQ FMan v3 1g port #0 device tree + * + * Copyright 2012-2015 Freescale Semiconductor Inc. + * -+ * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + */ + +fman@1a00000 { @@ -9807,12 +9909,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- /dev/null +++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-1.dtsi @@ -0,0 +1,42 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * QorIQ FMan v3 1g port #1 device tree + * + * Copyright 2012-2015 Freescale Semiconductor Inc. + * -+ * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + */ + +fman@1a00000 { @@ -9852,12 +9954,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- /dev/null +++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-2.dtsi @@ -0,0 +1,42 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * QorIQ FMan v3 1g port #2 device tree + * + * Copyright 2012-2015 Freescale Semiconductor Inc. + * -+ * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + */ + +fman@1a00000 { @@ -9897,12 +9999,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- /dev/null +++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-3.dtsi @@ -0,0 +1,42 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * QorIQ FMan v3 1g port #3 device tree + * + * Copyright 2012-2015 Freescale Semiconductor Inc. + * -+ * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + */ + +fman@1a00000 { @@ -9942,12 +10044,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- /dev/null +++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-4.dtsi @@ -0,0 +1,42 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * QorIQ FMan v3 1g port #4 device tree + * + * Copyright 2012-2015 Freescale Semiconductor Inc. + * -+ * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + */ + +fman@1a00000 { @@ -9987,12 +10089,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- /dev/null +++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-5.dtsi @@ -0,0 +1,42 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * QorIQ FMan v3 1g port #5 device tree + * + * Copyright 2012-2015 Freescale Semiconductor Inc. + * -+ * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + */ + +fman@1a00000 { @@ -10082,12 +10184,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- /dev/null +++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi @@ -0,0 +1,130 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * QorIQ FMan v3 device tree + * + * Copyright 2012-2015 Freescale Semiconductor Inc. + * -+ * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + */ + +fman0: fman@1a00000 { @@ -10213,110 +10315,134 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + }; +}; --- /dev/null -+++ b/arch/arm64/boot/dts/freescale/qoriq-qman1-portals.dtsi -@@ -0,0 +1,104 @@ ++++ b/arch/arm64/boot/dts/freescale/qoriq-qman-portals-sdk.dtsi +@@ -0,0 +1,38 @@ +/* -+ * QorIQ QMan Portals device tree ++ * QorIQ QMan SDK Portals device tree nodes + * + * Copyright 2011-2016 Freescale Semiconductor Inc. ++ * Copyright 2017 NXP + * + * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) + */ + +&qportals { ++ qman-fqids@0 { ++ compatible = "fsl,fqid-range"; ++ fsl,fqid-range = <256 256>; ++ }; ++ ++ qman-fqids@1 { ++ compatible = "fsl,fqid-range"; ++ fsl,fqid-range = <32768 32768>; ++ }; ++ ++ qman-pools@0 { ++ compatible = "fsl,pool-channel-range"; ++ fsl,pool-channel-range = <0x401 0xf>; ++ }; ++ ++ qman-cgrids@0 { ++ compatible = "fsl,cgrid-range"; ++ fsl,cgrid-range = <0 256>; ++ }; ++ ++ qman-ceetm@0 { ++ compatible = "fsl,qman-ceetm"; ++ fsl,ceetm-lfqid-range = <0xf00000 0x1000>; ++ fsl,ceetm-sp-range = <0 16>; ++ fsl,ceetm-lni-range = <0 8>; ++ fsl,ceetm-channel-range = <0 32>; ++ }; ++}; +--- /dev/null ++++ b/arch/arm64/boot/dts/freescale/qoriq-qman-portals.dtsi +@@ -0,0 +1,87 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * QorIQ QMan Portals device tree ++ * ++ * Copyright 2011-2016 Freescale Semiconductor Inc. ++ * ++ */ ++ ++&qportals { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + + qportal0: qman-portal@0 { ++ /* ++ * bootloader fix-ups are expected to provide the ++ * "fsl,bman-portal-<hardware revision>" compatible ++ */ + compatible = "fsl,qman-portal"; -+ reg = <0x0 0x4000 0x4000000 0x4000>; -+ interrupts = <0 172 0x4>; ++ reg = <0x0 0x4000>, <0x4000000 0x4000>; ++ interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>; + cell-index = <0>; + }; + + qportal1: qman-portal@10000 { + compatible = "fsl,qman-portal"; -+ reg = <0x10000 0x4000 0x4010000 0x4000>; -+ interrupts = <0 174 0x4>; ++ reg = <0x10000 0x4000>, <0x4010000 0x4000>; ++ interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>; + cell-index = <1>; + }; + + qportal2: qman-portal@20000 { + compatible = "fsl,qman-portal"; -+ reg = <0x20000 0x4000 0x4020000 0x4000>; -+ interrupts = <0 176 0x4>; ++ reg = <0x20000 0x4000>, <0x4020000 0x4000>; ++ interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>; + cell-index = <2>; + }; + + qportal3: qman-portal@30000 { + compatible = "fsl,qman-portal"; -+ reg = <0x30000 0x4000 0x4030000 0x4000>; -+ interrupts = <0 178 0x4>; ++ reg = <0x30000 0x4000>, <0x4030000 0x4000>; ++ interrupts = <GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>; + cell-index = <3>; + }; + + qportal4: qman-portal@40000 { + compatible = "fsl,qman-portal"; -+ reg = <0x40000 0x4000 0x4040000 0x4000>; -+ interrupts = <0 180 0x4>; ++ reg = <0x40000 0x4000>, <0x4040000 0x4000>; ++ interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>; + cell-index = <4>; + }; + + qportal5: qman-portal@50000 { + compatible = "fsl,qman-portal"; -+ reg = <0x50000 0x4000 0x4050000 0x4000>; -+ interrupts = <0 182 0x4>; ++ reg = <0x50000 0x4000>, <0x4050000 0x4000>; ++ interrupts = <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>; + cell-index = <5>; + }; + + qportal6: qman-portal@60000 { + compatible = "fsl,qman-portal"; -+ reg = <0x60000 0x4000 0x4060000 0x4000>; -+ interrupts = <0 184 0x4>; ++ reg = <0x60000 0x4000>, <0x4060000 0x4000>; ++ interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>; + cell-index = <6>; + }; + + qportal7: qman-portal@70000 { + compatible = "fsl,qman-portal"; -+ reg = <0x70000 0x4000 0x4070000 0x4000>; -+ interrupts = <0 186 0x4>; ++ reg = <0x70000 0x4000>, <0x4070000 0x4000>; ++ interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>; + cell-index = <7>; + }; + + qportal8: qman-portal@80000 { + compatible = "fsl,qman-portal"; -+ reg = <0x80000 0x4000 0x4080000 0x4000>; -+ interrupts = <0 188 0x4>; ++ reg = <0x80000 0x4000>, <0x4080000 0x4000>; ++ interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>; + cell-index = <8>; + }; + -+ qman-fqids@0 { -+ compatible = "fsl,fqid-range"; -+ fsl,fqid-range = <256 256>; -+ }; -+ -+ qman-fqids@1 { -+ compatible = "fsl,fqid-range"; -+ fsl,fqid-range = <32768 32768>; -+ }; -+ -+ qman-pools@0 { -+ compatible = "fsl,pool-channel-range"; -+ fsl,pool-channel-range = <0x401 0xf>; -+ }; -+ -+ qman-cgrids@0 { -+ compatible = "fsl,cgrid-range"; -+ fsl,cgrid-range = <0 256>; -+ }; -+ -+ qman-ceetm@0 { -+ compatible = "fsl,qman-ceetm"; -+ fsl,ceetm-lfqid-range = <0xf00000 0x1000>; -+ fsl,ceetm-sp-range = <0 12>; -+ fsl,ceetm-lni-range = <0 8>; -+ fsl,ceetm-channel-range = <0 32>; ++ qportal9: qman-portal@90000 { ++ compatible = "fsl,qman-portal"; ++ reg = <0x90000 0x4000>, <0x4090000 0x4000>; ++ interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>; ++ cell-index = <9>; + }; +}; --- a/arch/powerpc/boot/dts/fsl/qoriq-bman1-portals.dtsi diff --git a/target/linux/layerscape/patches-4.9/304-dts-layerscape-add-traverse-ls1043.patch b/target/linux/layerscape/patches-4.9/303-dts-layerscape-add-traverse-ls1043.patch index 90ebc202af..c57fb0985b 100644 --- a/target/linux/layerscape/patches-4.9/304-dts-layerscape-add-traverse-ls1043.patch +++ b/target/linux/layerscape/patches-4.9/303-dts-layerscape-add-traverse-ls1043.patch @@ -11,7 +11,7 @@ Signed-off-by: Mathew McBride <matt@traverse.com.au> --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile -@@ -20,7 +20,10 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2 +@@ -21,7 +21,10 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-simu.dtb dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2088a-qds.dtb dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2088a-rdb.dtb diff --git a/target/linux/layerscape/patches-4.9/401-mtd-spi-nor-support-layerscape.patch b/target/linux/layerscape/patches-4.9/401-mtd-spi-nor-support-layerscape.patch index e8fc1ec2ba..00ce333559 100644 --- a/target/linux/layerscape/patches-4.9/401-mtd-spi-nor-support-layerscape.patch +++ b/target/linux/layerscape/patches-4.9/401-mtd-spi-nor-support-layerscape.patch @@ -1,7 +1,7 @@ -From 825d57369b196b64387348922b47adc5b651622c Mon Sep 17 00:00:00 2001 +From c03c545e064a81515fe109ddcc4ecb3895528e58 Mon Sep 17 00:00:00 2001 From: Yangbo Lu <yangbo.lu@nxp.com> -Date: Wed, 17 Jan 2018 14:55:47 +0800 -Subject: [PATCH 05/30] mtd: spi-nor: support layerscape +Date: Fri, 6 Jul 2018 15:32:05 +0800 +Subject: [PATCH] mtd: spi-nor: support layerscape This is an integrated patch for layerscape qspi support. @@ -17,11 +17,12 @@ Signed-off-by: L. D. Pinney <ldpinney@gmail.com> Signed-off-by: Ash Benz <ash.benz@bk.ru> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- + drivers/mtd/devices/m25p80.c | 3 +- drivers/mtd/mtdchar.c | 2 +- - drivers/mtd/spi-nor/fsl-quadspi.c | 327 +++++++++++++++++++++++++++++++------- - drivers/mtd/spi-nor/spi-nor.c | 136 ++++++++++++++-- + drivers/mtd/spi-nor/fsl-quadspi.c | 327 ++++++++++++++++++++++++------ + drivers/mtd/spi-nor/spi-nor.c | 141 ++++++++++++- include/linux/mtd/spi-nor.h | 14 +- - 4 files changed, 409 insertions(+), 70 deletions(-) + 5 files changed, 416 insertions(+), 71 deletions(-) --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -758,9 +759,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) }, { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) }, -@@ -1131,6 +1152,9 @@ static const struct flash_info spi_nor_i +@@ -1130,7 +1151,15 @@ static const struct flash_info spi_nor_i + { "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K) }, { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) }, { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) }, ++ { ++ "w25q16dw", INFO(0xef6015, 0, 64 * 1024, 32, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | ++ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) ++ }, { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, + { "w25q20cl", INFO(0xef4012, 0, 64 * 1024, 4, SECT_4K) }, + { "w25q20bw", INFO(0xef5012, 0, 64 * 1024, 4, SECT_4K) }, @@ -768,7 +775,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, { "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64, -@@ -1197,6 +1221,53 @@ static const struct flash_info *spi_nor_ +@@ -1197,6 +1226,53 @@ static const struct flash_info *spi_nor_ id[0], id[1], id[2]); return ERR_PTR(-ENODEV); } @@ -822,7 +829,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) -@@ -1416,7 +1487,7 @@ static int macronix_quad_enable(struct s +@@ -1416,7 +1492,7 @@ static int macronix_quad_enable(struct s * Write status Register and configuration register with 2 bytes * The first byte will be written to the status register, while the * second byte will be written to the configuration register. @@ -831,7 +838,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> */ static int write_sr_cr(struct spi_nor *nor, u16 val) { -@@ -1464,6 +1535,24 @@ static int spansion_quad_enable(struct s +@@ -1464,6 +1540,24 @@ static int spansion_quad_enable(struct s return 0; } @@ -856,7 +863,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info) { int status; -@@ -1610,9 +1699,25 @@ int spi_nor_scan(struct spi_nor *nor, co +@@ -1610,9 +1704,25 @@ int spi_nor_scan(struct spi_nor *nor, co write_sr(nor, 0); spi_nor_wait_till_ready(nor); } @@ -882,7 +889,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> mtd->priv = nor; mtd->type = MTD_NORFLASH; mtd->writesize = 1; -@@ -1646,6 +1751,8 @@ int spi_nor_scan(struct spi_nor *nor, co +@@ -1646,6 +1756,8 @@ int spi_nor_scan(struct spi_nor *nor, co nor->flags |= SNOR_F_USE_FSR; if (info->flags & SPI_NOR_HAS_TB) nor->flags |= SNOR_F_HAS_SR_TB; @@ -891,7 +898,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> #ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS /* prefer "small sector" erase if possible */ -@@ -1685,9 +1792,15 @@ int spi_nor_scan(struct spi_nor *nor, co +@@ -1685,9 +1797,15 @@ int spi_nor_scan(struct spi_nor *nor, co /* Some devices cannot do fast-read, no matter what DT tells us */ if (info->flags & SPI_NOR_NO_FR) nor->flash_read = SPI_NOR_NORMAL; @@ -910,7 +917,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> ret = set_quad_mode(nor, info); if (ret) { dev_err(dev, "quad mode not supported\n"); -@@ -1700,6 +1813,9 @@ int spi_nor_scan(struct spi_nor *nor, co +@@ -1700,6 +1818,9 @@ int spi_nor_scan(struct spi_nor *nor, co /* Default commands */ switch (nor->flash_read) { diff --git a/target/linux/layerscape/patches-4.9/701-sdk_dpaa-support-layerscape.patch b/target/linux/layerscape/patches-4.9/701-sdk_dpaa-support-layerscape.patch index c318c579b0..0ea829aef2 100644 --- a/target/linux/layerscape/patches-4.9/701-sdk_dpaa-support-layerscape.patch +++ b/target/linux/layerscape/patches-4.9/701-sdk_dpaa-support-layerscape.patch @@ -1,7 +1,7 @@ -From 2f887ade916e7e1de2f8a84d3902aaa30af4b163 Mon Sep 17 00:00:00 2001 +From 6cc4cbfd0456c752f9f59d7d07fbb4b514dc6909 Mon Sep 17 00:00:00 2001 From: Yangbo Lu <yangbo.lu@nxp.com> -Date: Wed, 17 Jan 2018 14:59:15 +0800 -Subject: [PATCH 07/30] sdk_dpaa: support layerscape +Date: Thu, 5 Jul 2018 16:25:00 +0800 +Subject: [PATCH 07/32] sdk_dpaa: support layerscape This is an integrated patch for layerscape dpaa1-sdk support. @@ -12,264 +12,264 @@ Signed-off-by: Madalin Bucur <madalin.bucur@nxp.com> Signed-off-by: Mathew McBride <matt@traverse.com.au> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- - drivers/net/ethernet/freescale/sdk_dpaa/Kconfig | 196 + - drivers/net/ethernet/freescale/sdk_dpaa/Makefile | 46 + - .../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 | 180 + - .../net/ethernet/freescale/sdk_dpaa/dpaa_debugfs.h | 43 + - drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c | 1224 ++++ - drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h | 687 ++ - .../ethernet/freescale/sdk_dpaa/dpaa_eth_base.c | 205 + - .../ethernet/freescale/sdk_dpaa/dpaa_eth_base.h | 49 + - .../ethernet/freescale/sdk_dpaa/dpaa_eth_ceetm.c | 2013 ++++++ - .../ethernet/freescale/sdk_dpaa/dpaa_eth_ceetm.h | 238 + - .../ethernet/freescale/sdk_dpaa/dpaa_eth_common.c | 1802 +++++ - .../ethernet/freescale/sdk_dpaa/dpaa_eth_common.h | 225 + - .../ethernet/freescale/sdk_dpaa/dpaa_eth_proxy.c | 381 + - .../net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c | 1168 +++ - .../ethernet/freescale/sdk_dpaa/dpaa_eth_sysfs.c | 278 + - .../ethernet/freescale/sdk_dpaa/dpaa_eth_trace.h | 144 + - .../net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c | 544 ++ - drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ptp.c | 291 + - drivers/net/ethernet/freescale/sdk_dpaa/mac-api.c | 907 +++ - drivers/net/ethernet/freescale/sdk_dpaa/mac.c | 489 ++ - drivers/net/ethernet/freescale/sdk_dpaa/mac.h | 135 + - .../net/ethernet/freescale/sdk_dpaa/offline_port.c | 848 +++ - .../net/ethernet/freescale/sdk_dpaa/offline_port.h | 59 + - drivers/net/ethernet/freescale/sdk_fman/Kconfig | 153 + - 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 | 28 + - .../freescale/sdk_fman/Peripherals/FM/MAC/dtsec.c | 1465 ++++ - .../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 | 674 ++ - .../freescale/sdk_fman/Peripherals/FM/MAC/fm_mac.h | 226 + - .../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 | 532 ++ - .../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 | 1153 +++ - .../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 | 1017 +++ - .../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 | 26 + - .../freescale/sdk_fman/Peripherals/FM/Pcd/crc64.h | 360 + - .../freescale/sdk_fman/Peripherals/FM/Pcd/fm_cc.c | 7582 ++++++++++++++++++++ - .../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 | 5571 ++++++++++++++ - .../sdk_fman/Peripherals/FM/Pcd/fm_manip.h | 555 ++ - .../freescale/sdk_fman/Peripherals/FM/Pcd/fm_pcd.c | 2095 ++++++ - .../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 | 1847 +++++ - .../sdk_fman/Peripherals/FM/Pcd/fm_plcr.h | 165 + - .../freescale/sdk_fman/Peripherals/FM/Pcd/fm_prs.c | 423 ++ - .../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 | 5216 ++++++++++++++ - .../freescale/sdk_fman/Peripherals/FM/fm.h | 648 ++ - .../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 | 1398 ++++ - .../sdk_fman/Peripherals/FM/inc/fm_common.h | 1214 ++++ - .../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 | 620 ++ - 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 | 210 + - .../freescale/sdk_fman/inc/Peripherals/fm_ext.h | 1731 +++++ - .../sdk_fman/inc/Peripherals/fm_mac_ext.h | 887 +++ - .../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 | 3974 ++++++++++ - .../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 | 90 + - .../freescale/sdk_fman/inc/cores/arm_ext.h | 55 + - .../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 | 208 + - .../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 | 52 + - .../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 | 434 ++ - .../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 | 291 + - .../sdk_fman/inc/integrations/FMANV3H/part_ext.h | 71 + - .../integrations/FMANV3H/part_integration_ext.h | 304 + - .../integrations/FMANV3L/dpaa_integration_ext.h | 293 + - .../sdk_fman/inc/integrations/FMANV3L/part_ext.h | 59 + - .../integrations/FMANV3L/part_integration_ext.h | 304 + - .../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 + - .../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 | 100 + - .../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 | 62 + - .../ethernet/freescale/sdk_fman/inc/xx_common.h | 56 + - .../net/ethernet/freescale/sdk_fman/inc/xx_ext.h | 791 ++ - .../ethernet/freescale/sdk_fman/ls1043_dflags.h | 56 + - .../net/ethernet/freescale/sdk_fman/ncsw_config.mk | 53 + - .../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 | 208 + - .../sdk_fman/src/inc/wrapper/fsl_fman_test.h | 84 + - .../sdk_fman/src/inc/wrapper/lnxwrp_exp_sym.h | 130 + - .../sdk_fman/src/inc/wrapper/lnxwrp_fm_ext.h | 163 + - .../sdk_fman/src/inc/wrapper/lnxwrp_fsl_fman.h | 921 +++ - .../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 | 2908 ++++++++ - .../freescale/sdk_fman/src/wrapper/lnxwrp_fm.h | 294 + - .../sdk_fman/src/wrapper/lnxwrp_fm_port.c | 1480 ++++ - .../sdk_fman/src/wrapper/lnxwrp_ioctls_fm.c | 4854 +++++++++++++ - .../sdk_fman/src/wrapper/lnxwrp_ioctls_fm_compat.c | 1297 ++++ - .../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 | 1268 ++++ - .../sdk_fman/src/wrapper/lnxwrp_sysfs_fm_port.h | 56 + - .../ethernet/freescale/sdk_fman/src/xx/Makefile | 18 + - .../freescale/sdk_fman/src/xx/module_strings.c | 46 + - .../freescale/sdk_fman/src/xx/xx_arm_linux.c | 905 +++ - .../ethernet/freescale/sdk_fman/src/xx/xx_linux.c | 918 +++ - drivers/staging/fsl_qbman/Kconfig | 228 + - drivers/staging/fsl_qbman/Makefile | 28 + - drivers/staging/fsl_qbman/bman_config.c | 720 ++ - drivers/staging/fsl_qbman/bman_debugfs.c | 119 + - drivers/staging/fsl_qbman/bman_driver.c | 575 ++ - drivers/staging/fsl_qbman/bman_high.c | 1145 +++ - drivers/staging/fsl_qbman/bman_low.h | 565 ++ - drivers/staging/fsl_qbman/bman_private.h | 166 + - 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 | 259 + - drivers/staging/fsl_qbman/dpa_sys_arm.h | 95 + - 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 | 2007 ++++++ - drivers/staging/fsl_qbman/fsl_usdpaa_irq.c | 289 + - drivers/staging/fsl_qbman/qbman_driver.c | 88 + - drivers/staging/fsl_qbman/qman_config.c | 1224 ++++ - drivers/staging/fsl_qbman/qman_debugfs.c | 1594 ++++ - drivers/staging/fsl_qbman/qman_driver.c | 977 +++ - drivers/staging/fsl_qbman/qman_high.c | 5669 +++++++++++++++ - drivers/staging/fsl_qbman/qman_low.h | 1442 ++++ - drivers/staging/fsl_qbman/qman_private.h | 398 + - drivers/staging/fsl_qbman/qman_test.c | 57 + - drivers/staging/fsl_qbman/qman_test.h | 45 + - drivers/staging/fsl_qbman/qman_test_high.c | 216 + - drivers/staging/fsl_qbman/qman_test_hotpotato.c | 502 ++ - drivers/staging/fsl_qbman/qman_utility.c | 129 + - include/linux/fsl_bman.h | 532 ++ - include/linux/fsl_qman.h | 3888 ++++++++++ - include/linux/fsl_usdpaa.h | 372 + - 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 | 973 +++ - .../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 ++ - 257 files changed, 153236 insertions(+) + .../net/ethernet/freescale/sdk_dpaa/Kconfig | 196 + + .../net/ethernet/freescale/sdk_dpaa/Makefile | 46 + + .../ethernet/freescale/sdk_dpaa/dpaa_1588.c | 580 ++ + .../ethernet/freescale/sdk_dpaa/dpaa_1588.h | 138 + + .../freescale/sdk_dpaa/dpaa_debugfs.c | 180 + + .../freescale/sdk_dpaa/dpaa_debugfs.h | 43 + + .../ethernet/freescale/sdk_dpaa/dpaa_eth.c | 1224 +++ + .../ethernet/freescale/sdk_dpaa/dpaa_eth.h | 687 ++ + .../freescale/sdk_dpaa/dpaa_eth_base.c | 205 + + .../freescale/sdk_dpaa/dpaa_eth_base.h | 49 + + .../freescale/sdk_dpaa/dpaa_eth_ceetm.c | 2115 +++++ + .../freescale/sdk_dpaa/dpaa_eth_ceetm.h | 240 + + .../freescale/sdk_dpaa/dpaa_eth_common.c | 1802 ++++ + .../freescale/sdk_dpaa/dpaa_eth_common.h | 225 + + .../freescale/sdk_dpaa/dpaa_eth_proxy.c | 381 + + .../ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c | 1193 +++ + .../freescale/sdk_dpaa/dpaa_eth_sysfs.c | 278 + + .../freescale/sdk_dpaa/dpaa_eth_trace.h | 144 + + .../freescale/sdk_dpaa/dpaa_ethtool.c | 544 ++ + .../ethernet/freescale/sdk_dpaa/dpaa_ptp.c | 291 + + .../net/ethernet/freescale/sdk_dpaa/mac-api.c | 931 ++ + drivers/net/ethernet/freescale/sdk_dpaa/mac.c | 489 ++ + drivers/net/ethernet/freescale/sdk_dpaa/mac.h | 135 + + .../freescale/sdk_dpaa/offline_port.c | 848 ++ + .../freescale/sdk_dpaa/offline_port.h | 59 + + .../net/ethernet/freescale/sdk_fman/Kconfig | 153 + + .../net/ethernet/freescale/sdk_fman/Makefile | 11 + + .../sdk_fman/Peripherals/FM/HC/Makefile | 15 + + .../freescale/sdk_fman/Peripherals/FM/HC/hc.c | 1232 +++ + .../sdk_fman/Peripherals/FM/MAC/Makefile | 28 + + .../sdk_fman/Peripherals/FM/MAC/dtsec.c | 1504 ++++ + .../sdk_fman/Peripherals/FM/MAC/dtsec.h | 228 + + .../Peripherals/FM/MAC/dtsec_mii_acc.c | 97 + + .../Peripherals/FM/MAC/dtsec_mii_acc.h | 42 + + .../sdk_fman/Peripherals/FM/MAC/fm_mac.c | 674 ++ + .../sdk_fman/Peripherals/FM/MAC/fm_mac.h | 226 + + .../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 | 532 ++ + .../Peripherals/FM/MAC/fman_memac_mii_acc.c | 213 + + .../sdk_fman/Peripherals/FM/MAC/fman_tgec.c | 367 + + .../sdk_fman/Peripherals/FM/MAC/memac.c | 1153 +++ + .../sdk_fman/Peripherals/FM/MAC/memac.h | 110 + + .../Peripherals/FM/MAC/memac_mii_acc.c | 78 + + .../Peripherals/FM/MAC/memac_mii_acc.h | 73 + + .../sdk_fman/Peripherals/FM/MAC/tgec.c | 1017 +++ + .../sdk_fman/Peripherals/FM/MAC/tgec.h | 151 + + .../Peripherals/FM/MAC/tgec_mii_acc.c | 139 + + .../Peripherals/FM/MAC/tgec_mii_acc.h | 80 + + .../sdk_fman/Peripherals/FM/MACSEC/Makefile | 15 + + .../Peripherals/FM/MACSEC/fm_macsec.c | 237 + + .../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 + + .../sdk_fman/Peripherals/FM/Makefile | 23 + + .../sdk_fman/Peripherals/FM/Pcd/Makefile | 26 + + .../sdk_fman/Peripherals/FM/Pcd/crc64.h | 360 + + .../sdk_fman/Peripherals/FM/Pcd/fm_cc.c | 7582 +++++++++++++++++ + .../sdk_fman/Peripherals/FM/Pcd/fm_cc.h | 399 + + .../sdk_fman/Peripherals/FM/Pcd/fm_kg.c | 3242 +++++++ + .../sdk_fman/Peripherals/FM/Pcd/fm_kg.h | 206 + + .../sdk_fman/Peripherals/FM/Pcd/fm_manip.c | 5571 ++++++++++++ + .../sdk_fman/Peripherals/FM/Pcd/fm_manip.h | 555 ++ + .../sdk_fman/Peripherals/FM/Pcd/fm_pcd.c | 2095 +++++ + .../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 | 1847 ++++ + .../sdk_fman/Peripherals/FM/Pcd/fm_plcr.h | 165 + + .../sdk_fman/Peripherals/FM/Pcd/fm_prs.c | 423 + + .../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 +++ + .../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 ++++ + .../sdk_fman/Peripherals/FM/Rtc/Makefile | 15 + + .../sdk_fman/Peripherals/FM/Rtc/fm_rtc.c | 692 ++ + .../sdk_fman/Peripherals/FM/Rtc/fm_rtc.h | 96 + + .../sdk_fman/Peripherals/FM/Rtc/fman_rtc.c | 334 + + .../sdk_fman/Peripherals/FM/SP/Makefile | 15 + + .../sdk_fman/Peripherals/FM/SP/fm_sp.c | 757 ++ + .../sdk_fman/Peripherals/FM/SP/fm_sp.h | 85 + + .../sdk_fman/Peripherals/FM/SP/fman_sp.c | 197 + + .../freescale/sdk_fman/Peripherals/FM/fm.c | 5216 ++++++++++++ + .../freescale/sdk_fman/Peripherals/FM/fm.h | 648 ++ + .../sdk_fman/Peripherals/FM/fm_ipc.h | 465 + + .../sdk_fman/Peripherals/FM/fm_muram.c | 174 + + .../freescale/sdk_fman/Peripherals/FM/fman.c | 1398 +++ + .../sdk_fman/Peripherals/FM/inc/fm_common.h | 1214 +++ + .../sdk_fman/Peripherals/FM/inc/fm_hc.h | 93 + + .../Peripherals/FM/inc/fm_sp_common.h | 117 + + .../ethernet/freescale/sdk_fman/etc/Makefile | 12 + + .../ethernet/freescale/sdk_fman/etc/error.c | 95 + + .../ethernet/freescale/sdk_fman/etc/list.c | 71 + + .../ethernet/freescale/sdk_fman/etc/memcpy.c | 620 ++ + .../net/ethernet/freescale/sdk_fman/etc/mm.c | 1155 +++ + .../net/ethernet/freescale/sdk_fman/etc/mm.h | 105 + + .../ethernet/freescale/sdk_fman/etc/sprint.c | 81 + + .../freescale/sdk_fman/fmanv3h_dflags.h | 57 + + .../freescale/sdk_fman/fmanv3l_dflags.h | 56 + + .../inc/Peripherals/crc_mac_addr_ext.h | 364 + + .../sdk_fman/inc/Peripherals/dpaa_ext.h | 210 + + .../sdk_fman/inc/Peripherals/fm_ext.h | 1731 ++++ + .../sdk_fman/inc/Peripherals/fm_mac_ext.h | 887 ++ + .../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 | 3974 +++++++++ + .../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 + + .../freescale/sdk_fman/inc/core_ext.h | 90 + + .../freescale/sdk_fman/inc/cores/arm_ext.h | 55 + + .../freescale/sdk_fman/inc/cores/e500v2_ext.h | 476 ++ + .../freescale/sdk_fman/inc/cores/ppc_ext.h | 141 + + .../freescale/sdk_fman/inc/ddr_std_ext.h | 77 + + .../freescale/sdk_fman/inc/debug_ext.h | 233 + + .../freescale/sdk_fman/inc/endian_ext.h | 447 + + .../freescale/sdk_fman/inc/enet_ext.h | 205 + + .../freescale/sdk_fman/inc/error_ext.h | 529 ++ + .../freescale/sdk_fman/inc/etc/list_ext.h | 358 + + .../freescale/sdk_fman/inc/etc/mem_ext.h | 318 + + .../freescale/sdk_fman/inc/etc/memcpy_ext.h | 208 + + .../freescale/sdk_fman/inc/etc/mm_ext.h | 310 + + .../freescale/sdk_fman/inc/etc/sprint_ext.h | 118 + + .../inc/flib/common/arch/ppc_access.h | 37 + + .../sdk_fman/inc/flib/common/general.h | 52 + + .../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 ++ + .../sdk_fman/inc/flib/fsl_fman_dtsec.h | 1096 +++ + .../inc/flib/fsl_fman_dtsec_mii_acc.h | 107 + + .../freescale/sdk_fman/inc/flib/fsl_fman_kg.h | 514 ++ + .../sdk_fman/inc/flib/fsl_fman_memac.h | 434 + + .../inc/flib/fsl_fman_memac_mii_acc.h | 78 + + .../sdk_fman/inc/flib/fsl_fman_port.h | 593 ++ + .../sdk_fman/inc/flib/fsl_fman_prs.h | 102 + + .../sdk_fman/inc/flib/fsl_fman_rtc.h | 449 + + .../freescale/sdk_fman/inc/flib/fsl_fman_sp.h | 138 + + .../sdk_fman/inc/flib/fsl_fman_tgec.h | 479 ++ + .../FMANV3H/dpaa_integration_ext.h | 291 + + .../inc/integrations/FMANV3H/part_ext.h | 71 + + .../FMANV3H/part_integration_ext.h | 304 + + .../FMANV3L/dpaa_integration_ext.h | 293 + + .../inc/integrations/FMANV3L/part_ext.h | 59 + + .../FMANV3L/part_integration_ext.h | 304 + + .../LS1043/dpaa_integration_ext.h | 291 + + .../inc/integrations/LS1043/part_ext.h | 64 + + .../LS1043/part_integration_ext.h | 185 + + .../integrations/P1023/dpaa_integration_ext.h | 213 + + .../inc/integrations/P1023/part_ext.h | 82 + + .../integrations/P1023/part_integration_ext.h | 635 ++ + .../P3040_P4080_P5020/dpaa_integration_ext.h | 276 + + .../integrations/P3040_P4080_P5020/part_ext.h | 83 + + .../P3040_P4080_P5020/part_integration_ext.h | 336 + + .../freescale/sdk_fman/inc/math_ext.h | 100 + + .../freescale/sdk_fman/inc/ncsw_ext.h | 435 + + .../ethernet/freescale/sdk_fman/inc/net_ext.h | 430 + + .../ethernet/freescale/sdk_fman/inc/std_ext.h | 48 + + .../freescale/sdk_fman/inc/stdarg_ext.h | 49 + + .../freescale/sdk_fman/inc/stdlib_ext.h | 162 + + .../freescale/sdk_fman/inc/string_ext.h | 56 + + .../freescale/sdk_fman/inc/types_ext.h | 62 + + .../freescale/sdk_fman/inc/xx_common.h | 56 + + .../ethernet/freescale/sdk_fman/inc/xx_ext.h | 791 ++ + .../freescale/sdk_fman/ls1043_dflags.h | 56 + + .../freescale/sdk_fman/ncsw_config.mk | 53 + + .../freescale/sdk_fman/p1023_dflags.h | 65 + + .../sdk_fman/p3040_4080_5020_dflags.h | 62 + + .../ethernet/freescale/sdk_fman/src/Makefile | 11 + + .../sdk_fman/src/inc/system/sys_ext.h | 118 + + .../sdk_fman/src/inc/system/sys_io_ext.h | 46 + + .../freescale/sdk_fman/src/inc/types_linux.h | 208 + + .../sdk_fman/src/inc/wrapper/fsl_fman_test.h | 84 + + .../sdk_fman/src/inc/wrapper/lnxwrp_exp_sym.h | 130 + + .../sdk_fman/src/inc/wrapper/lnxwrp_fm_ext.h | 163 + + .../src/inc/wrapper/lnxwrp_fsl_fman.h | 921 ++ + .../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 + + .../sdk_fman/src/wrapper/fman_test.c | 1665 ++++ + .../sdk_fman/src/wrapper/lnxwrp_fm.c | 2908 +++++++ + .../sdk_fman/src/wrapper/lnxwrp_fm.h | 294 + + .../sdk_fman/src/wrapper/lnxwrp_fm_port.c | 1512 ++++ + .../sdk_fman/src/wrapper/lnxwrp_ioctls_fm.c | 4854 +++++++++++ + .../src/wrapper/lnxwrp_ioctls_fm_compat.c | 1297 +++ + .../src/wrapper/lnxwrp_ioctls_fm_compat.h | 755 ++ + .../sdk_fman/src/wrapper/lnxwrp_resources.h | 121 + + .../src/wrapper/lnxwrp_resources_ut.c | 191 + + .../src/wrapper/lnxwrp_resources_ut.h | 144 + + .../src/wrapper/lnxwrp_resources_ut.make | 28 + + .../sdk_fman/src/wrapper/lnxwrp_sysfs.c | 60 + + .../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 + + .../src/wrapper/lnxwrp_sysfs_fm_port.c | 1268 +++ + .../src/wrapper/lnxwrp_sysfs_fm_port.h | 56 + + .../freescale/sdk_fman/src/xx/Makefile | 18 + + .../sdk_fman/src/xx/module_strings.c | 46 + + .../freescale/sdk_fman/src/xx/xx_arm_linux.c | 905 ++ + .../freescale/sdk_fman/src/xx/xx_linux.c | 918 ++ + drivers/staging/fsl_qbman/Kconfig | 228 + + drivers/staging/fsl_qbman/Makefile | 28 + + drivers/staging/fsl_qbman/bman_config.c | 720 ++ + drivers/staging/fsl_qbman/bman_debugfs.c | 119 + + drivers/staging/fsl_qbman/bman_driver.c | 575 ++ + drivers/staging/fsl_qbman/bman_high.c | 1145 +++ + drivers/staging/fsl_qbman/bman_low.h | 565 ++ + drivers/staging/fsl_qbman/bman_private.h | 166 + + 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 | 259 + + drivers/staging/fsl_qbman/dpa_sys_arm.h | 95 + + 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 | 2007 +++++ + drivers/staging/fsl_qbman/fsl_usdpaa_irq.c | 289 + + drivers/staging/fsl_qbman/qbman_driver.c | 88 + + drivers/staging/fsl_qbman/qman_config.c | 1224 +++ + drivers/staging/fsl_qbman/qman_debugfs.c | 1594 ++++ + drivers/staging/fsl_qbman/qman_driver.c | 977 +++ + drivers/staging/fsl_qbman/qman_high.c | 5652 ++++++++++++ + drivers/staging/fsl_qbman/qman_low.h | 1442 ++++ + drivers/staging/fsl_qbman/qman_private.h | 398 + + drivers/staging/fsl_qbman/qman_test.c | 57 + + drivers/staging/fsl_qbman/qman_test.h | 45 + + drivers/staging/fsl_qbman/qman_test_high.c | 216 + + .../staging/fsl_qbman/qman_test_hotpotato.c | 502 ++ + drivers/staging/fsl_qbman/qman_utility.c | 129 + + include/linux/fsl_bman.h | 532 ++ + include/linux/fsl_qman.h | 3900 +++++++++ + include/linux/fsl_usdpaa.h | 372 + + include/uapi/linux/fmd/Kbuild | 5 + + include/uapi/linux/fmd/Peripherals/Kbuild | 4 + + .../uapi/linux/fmd/Peripherals/fm_ioctls.h | 628 ++ + .../linux/fmd/Peripherals/fm_pcd_ioctls.h | 3084 +++++++ + .../linux/fmd/Peripherals/fm_port_ioctls.h | 973 +++ + .../linux/fmd/Peripherals/fm_test_ioctls.h | 208 + + include/uapi/linux/fmd/integrations/Kbuild | 1 + + .../fmd/integrations/integration_ioctls.h | 56 + + include/uapi/linux/fmd/ioctls.h | 96 + + include/uapi/linux/fmd/net_ioctls.h | 430 + + 257 files changed, 153455 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 @@ -3908,7 +3908,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#endif /* __DPAA_ETH_BASE_H */ --- /dev/null +++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_ceetm.c -@@ -0,0 +1,2013 @@ +@@ -0,0 +1,2115 @@ +/* Copyright 2008-2016 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without @@ -3976,6 +3976,76 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + } +} + ++/* Wait for the DPAA Eth driver WQ TX FQs to empty */ ++static void dpaa_drain_fqs(struct net_device *dev) ++{ ++ const struct dpa_priv_s *priv = netdev_priv(dev); ++ struct qm_mcr_queryfq_np np; ++ struct qman_fq *fq; ++ int ret, i; ++ ++ for (i = 0; i < DPAA_ETH_TX_QUEUES; i ++) { ++ fq = priv->egress_fqs[i]; ++ while (true) { ++ ret = qman_query_fq_np(fq, &np); ++ if (unlikely(ret)) { ++ pr_err(KBUILD_BASENAME ++ " : %s : unable to query FQ %x: %d\n", ++ __func__, fq->fqid, ret); ++ break; ++ } ++ ++ if (np.frm_cnt == 0) ++ break; ++ } ++ } ++} ++ ++/* Wait for the DPAA CEETM TX CQs to empty */ ++static void ceetm_drain_class(struct ceetm_class *cl) ++{ ++ struct qm_mcr_ceetm_cq_query cq_query; ++ struct qm_ceetm_cq *cq; ++ unsigned int idx; ++ int ret; ++ ++ if (!cl) ++ return; ++ ++ switch (cl->type) { ++ case CEETM_ROOT: ++ /* The ROOT classes aren't directly linked to CEETM CQs */ ++ return; ++ case CEETM_PRIO: ++ cq = (struct qm_ceetm_cq*)cl->prio.cq; ++ break; ++ case CEETM_WBFS: ++ cq = (struct qm_ceetm_cq*)cl->wbfs.cq; ++ break; ++ } ++ ++ if (!cq || !cl->ch) ++ return; ++ ++ /* Build the query CQID by merging the channel and the CQ IDs */ ++ idx = (cq->parent->idx << 4) | cq->idx; ++ ++ while (true) { ++ ret = qman_ceetm_query_cq(idx, ++ cl->ch->dcp_idx, ++ &cq_query); ++ if (unlikely(ret)) { ++ pr_err(KBUILD_BASENAME ++ " : %s : unable to query CQ %x: %d\n", ++ __func__, idx, ret); ++ break; ++ } ++ ++ if (cq_query.frm_cnt == 0) ++ break; ++ } ++} ++ +/* Enqueue Rejection Notification callback */ +static void ceetm_ern(struct qman_portal *portal, struct qman_fq *fq, + const struct qm_mr_entry *msg) @@ -4153,7 +4223,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +/* Configure a prio ceetm class */ +static int ceetm_config_prio_cls(struct ceetm_class *cls, + struct net_device *dev, -+ struct qm_ceetm_channel *channel, + unsigned int id) +{ + int err; @@ -4164,22 +4233,22 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return err; + + /* Claim and configure the CCG */ -+ err = ceetm_config_ccg(&cls->prio.ccg, channel, id, cls->prio.fq, ++ err = ceetm_config_ccg(&cls->prio.ccg, cls->ch, id, cls->prio.fq, + dpa_priv); + if (err) + return err; + + /* Claim and configure the CQ */ -+ err = qman_ceetm_cq_claim(&cls->prio.cq, channel, id, cls->prio.ccg); ++ err = qman_ceetm_cq_claim(&cls->prio.cq, cls->ch, id, cls->prio.ccg); + if (err) + return err; + + if (cls->shaped) { -+ err = qman_ceetm_channel_set_cq_cr_eligibility(channel, id, 1); ++ err = qman_ceetm_channel_set_cq_cr_eligibility(cls->ch, id, 1); + if (err) + return err; + -+ err = qman_ceetm_channel_set_cq_er_eligibility(channel, id, 1); ++ err = qman_ceetm_channel_set_cq_er_eligibility(cls->ch, id, 1); + if (err) + return err; + } @@ -4195,7 +4264,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +/* Configure a wbfs ceetm class */ +static int ceetm_config_wbfs_cls(struct ceetm_class *cls, + struct net_device *dev, -+ struct qm_ceetm_channel *channel, + unsigned int id, int type) +{ + int err; @@ -4206,17 +4274,17 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return err; + + /* Claim and configure the CCG */ -+ err = ceetm_config_ccg(&cls->wbfs.ccg, channel, id, cls->wbfs.fq, ++ err = ceetm_config_ccg(&cls->wbfs.ccg, cls->ch, id, cls->wbfs.fq, + dpa_priv); + if (err) + return err; + + /* Claim and configure the CQ */ + if (type == WBFS_GRP_B) -+ err = qman_ceetm_cq_claim_B(&cls->wbfs.cq, channel, id, ++ err = qman_ceetm_cq_claim_B(&cls->wbfs.cq, cls->ch, id, + cls->wbfs.ccg); + else -+ err = qman_ceetm_cq_claim_A(&cls->wbfs.cq, channel, id, ++ err = qman_ceetm_cq_claim_A(&cls->wbfs.cq, cls->ch, id, + cls->wbfs.ccg); + if (err) + return err; @@ -4264,6 +4332,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +/* Destroy a ceetm class */ +static void ceetm_cls_destroy(struct Qdisc *sch, struct ceetm_class *cl) +{ ++ struct net_device *dev = qdisc_dev(sch); ++ + if (!cl) + return; + @@ -4277,10 +4347,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + cl->root.child = NULL; + } + -+ if (cl->root.ch && qman_ceetm_channel_release(cl->root.ch)) ++ if (cl->ch && qman_ceetm_channel_release(cl->ch)) + pr_err(KBUILD_BASENAME + " : %s : error releasing the channel %d\n", -+ __func__, cl->root.ch->idx); ++ __func__, cl->ch->idx); + + break; + @@ -4290,6 +4360,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + cl->prio.child = NULL; + } + ++ /* We must make sure the CQ is empty before releasing it. ++ * Pause all transmissions while we wait for it to drain. ++ */ ++ netif_tx_stop_all_queues(dev); ++ ceetm_drain_class(cl); ++ + if (cl->prio.lfq && qman_ceetm_lfq_release(cl->prio.lfq)) + pr_err(KBUILD_BASENAME + " : %s : error releasing the LFQ %d\n", @@ -4310,9 +4386,16 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + if (cl->prio.cstats) + free_percpu(cl->prio.cstats); + ++ netif_tx_wake_all_queues(dev); + break; + + case CEETM_WBFS: ++ /* We must make sure the CQ is empty before releasing it. ++ * Pause all transmissions while we wait for it to drain. ++ */ ++ netif_tx_stop_all_queues(dev); ++ ceetm_drain_class(cl); ++ + if (cl->wbfs.lfq && qman_ceetm_lfq_release(cl->wbfs.lfq)) + pr_err(KBUILD_BASENAME + " : %s : error releasing the LFQ %d\n", @@ -4332,6 +4415,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + if (cl->wbfs.cstats) + free_percpu(cl->wbfs.cstats); ++ ++ netif_tx_wake_all_queues(dev); + } + + tcf_destroy_chain(&cl->filter_list); @@ -4386,7 +4471,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + if (!priv->root.qdiscs) + break; + -+ /* Remove the pfifo qdiscs */ ++ /* Destroy the pfifo qdiscs in case they haven't been attached ++ * to the netdev queues yet. ++ */ + for (ntx = 0; ntx < dev->num_tx_queues; ntx++) + if (priv->root.qdiscs[ntx]) + qdisc_destroy(priv->root.qdiscs[ntx]); @@ -4400,6 +4487,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + break; + + case CEETM_WBFS: ++ /* Reset the WBFS groups and priorities */ ++ if (priv->wbfs.ch) ++ qman_ceetm_channel_set_group(priv->wbfs.ch, 1, 0, 0); ++ + if (priv->wbfs.parent) + priv->wbfs.parent->prio.child = NULL; + break; @@ -4516,7 +4607,16 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + goto err_init_root; + } + -+ /* pre-allocate underlying pfifo qdiscs */ ++ /* Pre-allocate underlying pfifo qdiscs. ++ * ++ * We want to offload shaping and scheduling decisions to the hardware. ++ * The pfifo qdiscs will be attached to the netdev queues and will ++ * guide the traffic from the IP stack down to the driver with minimum ++ * interference. ++ * ++ * The CEETM qdiscs and classes will be crossed when the traffic ++ * reaches the driver. ++ */ + priv->root.qdiscs = kcalloc(dev->num_tx_queues, + sizeof(priv->root.qdiscs[0]), + GFP_KERNEL); @@ -4663,6 +4763,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + priv->shaped = parent_cl->shaped; + priv->prio.qcount = qopt->qcount; ++ priv->prio.ch = parent_cl->ch; + + /* Create and configure qcount child classes */ + for (i = 0; i < priv->prio.qcount; i++) { @@ -4688,6 +4789,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + child_cl->type = CEETM_PRIO; + child_cl->shaped = priv->shaped; + child_cl->prio.child = NULL; ++ child_cl->ch = priv->prio.ch; + + /* All shaped CQs have CR and ER enabled by default */ + child_cl->prio.cr = child_cl->shaped; @@ -4696,8 +4798,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + child_cl->prio.cq = NULL; + + /* Configure the corresponding hardware CQ */ -+ err = ceetm_config_prio_cls(child_cl, dev, -+ parent_cl->root.ch, i); ++ err = ceetm_config_prio_cls(child_cl, dev, i); + if (err) { + pr_err(KBUILD_BASENAME " : %s : failed to configure the ceetm prio class %X\n", + __func__, child_cl->common.classid); @@ -4729,7 +4830,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct ceetm_class *parent_cl, *child_cl, *root_cl; + struct Qdisc *parent_qdisc; + struct ceetm_qdisc *parent_priv; -+ struct qm_ceetm_channel *channel; + struct net_device *dev = qdisc_dev(sch); + + pr_debug(KBUILD_BASENAME " : %s : qdisc %X\n", __func__, sch->handle); @@ -4802,8 +4902,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + priv->wbfs.qcount = qopt->qcount; + priv->wbfs.cr = qopt->cr; + priv->wbfs.er = qopt->er; -+ -+ channel = root_cl->root.ch; ++ priv->wbfs.ch = parent_cl->ch; + + /* Configure the hardware wbfs channel groups */ + if (priv->wbfs.qcount == CEETM_MAX_WBFS_QCOUNT) { @@ -4818,7 +4917,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + /* Configure the group B */ + priv->wbfs.group_type = WBFS_GRP_B; + -+ err = qman_ceetm_channel_get_group(channel, &small_group, ++ err = qman_ceetm_channel_get_group(priv->wbfs.ch, &small_group, + &prio_a, &prio_b); + if (err) { + pr_err(KBUILD_BASENAME " : %s : failed to get group details\n", @@ -4836,7 +4935,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + /* Configure the small group A */ + priv->wbfs.group_type = WBFS_GRP_A; + -+ err = qman_ceetm_channel_get_group(channel, &small_group, ++ err = qman_ceetm_channel_get_group(priv->wbfs.ch, &small_group, + &prio_a, &prio_b); + if (err) { + pr_err(KBUILD_BASENAME " : %s : failed to get group details\n", @@ -4851,13 +4950,13 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + prio_b = prio_b ? : prio_a; + } + -+ err = qman_ceetm_channel_set_group(channel, small_group, prio_a, ++ err = qman_ceetm_channel_set_group(priv->wbfs.ch, small_group, prio_a, + prio_b); + if (err) + goto err_init_wbfs; + + if (priv->shaped) { -+ err = qman_ceetm_channel_set_group_cr_eligibility(channel, ++ err = qman_ceetm_channel_set_group_cr_eligibility(priv->wbfs.ch, + group_b, + priv->wbfs.cr); + if (err) { @@ -4866,7 +4965,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + goto err_init_wbfs; + } + -+ err = qman_ceetm_channel_set_group_er_eligibility(channel, ++ err = qman_ceetm_channel_set_group_er_eligibility(priv->wbfs.ch, + group_b, + priv->wbfs.er); + if (err) { @@ -4902,13 +5001,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + child_cl->wbfs.fq = NULL; + child_cl->wbfs.cq = NULL; + child_cl->wbfs.weight = qopt->qweight[i]; ++ child_cl->ch = priv->wbfs.ch; + + if (priv->wbfs.group_type == WBFS_GRP_B) + id = WBFS_GRP_B_OFFSET + i; + else + id = WBFS_GRP_A_OFFSET + i; + -+ err = ceetm_config_wbfs_cls(child_cl, dev, channel, id, ++ err = ceetm_config_wbfs_cls(child_cl, dev, id, + priv->wbfs.group_type); + if (err) { + pr_err(KBUILD_BASENAME " : %s : failed to configure the ceetm wbfs class %X\n", @@ -4994,7 +5094,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + switch (priv->type) { + case CEETM_ROOT: ++ netif_tx_stop_all_queues(dev); ++ dpaa_drain_fqs(dev); + ret = ceetm_init_root(sch, priv, qopt); ++ netif_tx_wake_all_queues(dev); + break; + case CEETM_PRIO: + ret = ceetm_init_prio(sch, priv, qopt); @@ -5070,9 +5173,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +{ + int err; + bool group_b; -+ struct qm_ceetm_channel *channel; -+ struct ceetm_class *prio_class, *root_class; -+ struct ceetm_qdisc *prio_qdisc; + + if (qopt->qcount) { + pr_err("CEETM: the qcount can not be modified\n"); @@ -5098,14 +5198,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + if (!priv->shaped) + return 0; + -+ prio_class = priv->wbfs.parent; -+ prio_qdisc = qdisc_priv(prio_class->parent); -+ root_class = prio_qdisc->prio.parent; -+ channel = root_class->root.ch; + group_b = priv->wbfs.group_type == WBFS_GRP_B; + + if (qopt->cr != priv->wbfs.cr) { -+ err = qman_ceetm_channel_set_group_cr_eligibility(channel, ++ err = qman_ceetm_channel_set_group_cr_eligibility(priv->wbfs.ch, + group_b, + qopt->cr); + if (err) @@ -5114,7 +5210,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + } + + if (qopt->er != priv->wbfs.er) { -+ err = qman_ceetm_channel_set_group_er_eligibility(channel, ++ err = qman_ceetm_channel_set_group_er_eligibility(priv->wbfs.ch, + group_b, + qopt->er); + if (err) @@ -5184,7 +5280,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return ret; +} + -+/* Attach the underlying pfifo qdiscs */ ++/* Graft the underlying pfifo qdiscs to the netdev queues. ++ * It's safe to remove our references at this point, since the kernel will ++ * destroy the qdiscs on its own and no cleanup from our part is required. ++ */ +static void ceetm_attach(struct Qdisc *sch) +{ + struct net_device *dev = qdisc_dev(sch); @@ -5200,6 +5299,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + if (old_qdisc) + qdisc_destroy(old_qdisc); + } ++ ++ kfree(priv->root.qdiscs); ++ priv->root.qdiscs = NULL; +} + +static unsigned long ceetm_cls_get(struct Qdisc *sch, u32 classid) @@ -5242,7 +5344,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + if (cl->shaped && cl->root.rate != copt->rate) { + bps = copt->rate << 3; /* Bps -> bps */ -+ err = qman_ceetm_channel_set_commit_rate_bps(cl->root.ch, bps, ++ err = qman_ceetm_channel_set_commit_rate_bps(cl->ch, bps, + dev->mtu); + if (err) + goto change_cls_err; @@ -5251,7 +5353,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + if (cl->shaped && cl->root.ceil != copt->ceil) { + bps = copt->ceil << 3; /* Bps -> bps */ -+ err = qman_ceetm_channel_set_excess_rate_bps(cl->root.ch, bps, ++ err = qman_ceetm_channel_set_excess_rate_bps(cl->ch, bps, + dev->mtu); + if (err) + goto change_cls_err; @@ -5259,7 +5361,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + } + + if (!cl->shaped && cl->root.tbl != copt->tbl) { -+ err = qman_ceetm_channel_set_weight(cl->root.ch, copt->tbl); ++ err = qman_ceetm_channel_set_weight(cl->ch, copt->tbl); + if (err) + goto change_cls_err; + cl->root.tbl = copt->tbl; @@ -5454,7 +5556,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + goto claim_err; + } + -+ cl->root.ch = channel; ++ cl->ch = channel; + + if (cl->shaped) { + /* Configure the channel shaper */ @@ -5924,7 +6026,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +module_exit(ceetm_unregister); --- /dev/null +++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_ceetm.h -@@ -0,0 +1,238 @@ +@@ -0,0 +1,240 @@ +/* Copyright 2008-2016 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without @@ -6048,12 +6150,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +struct prio_q { + __u16 qcount; + struct ceetm_class *parent; ++ struct qm_ceetm_channel *ch; +}; + +struct wbfs_q { + __u16 qcount; + int group_type; + struct ceetm_class *parent; ++ struct qm_ceetm_channel *ch; + __u16 cr; + __u16 er; +}; @@ -6091,7 +6195,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + bool wbfs_grp_b; + bool wbfs_grp_large; + struct Qdisc *child; -+ struct qm_ceetm_channel *ch; +}; + +struct prio_c { @@ -6120,6 +6223,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + int refcnt; /* usage count of this class */ + struct tcf_proto *filter_list; /* class attached filters */ + struct Qdisc *parent; ++ struct qm_ceetm_channel *ch; + bool shaped; + int type; /* ROOT/PRIO/WBFS */ + union { @@ -8582,7 +8686,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +module_exit(dpa_proxy_unload); --- /dev/null +++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c -@@ -0,0 +1,1168 @@ +@@ -0,0 +1,1193 @@ +/* Copyright 2012 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without @@ -8706,6 +8810,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + put_page(virt_to_head_page(new_buf)); + goto build_skb_failed; + } ++ ++ /* Store the skb back-pointer before the start of the buffer. ++ * Otherwise it will be overwritten by the FMan. ++ */ + DPA_WRITE_SKB_PTR(skb, skbh, new_buf, -1); + + addr = dma_map_single(dev, new_buf, @@ -8929,13 +9037,22 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * - 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 ++ * - the skb back-pointer is stored safely + */ ++ ++ /* guarantee both the minimum size and the minimum data offset */ + 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 && ++ /* Make sure there is enough space to store the skb back-pointer in ++ * the headroom, right before the start of the buffer. ++ * ++ * Guarantee that both maximum size and maximum data offsets aren't ++ * crossed. ++ */ ++ if (likely(new >= (skb->head + sizeof(void *)) && + new >= (skb->data - DPA_MAX_FD_OFFSET) && + skb_end_pointer(skb) - new <= DPA_RECYCLE_MAX_SIZE)) { + *new_buf_start = new; @@ -9273,6 +9390,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + dma_dir = DMA_BIDIRECTIONAL; + dma_map_size = dpa_bp->size; + ++ /* Store the skb back-pointer before the start of the buffer. ++ * Otherwise it will be overwritten by the FMan. ++ */ + DPA_WRITE_SKB_PTR(skb, skbh, buffer_start, -1); + *offset = skb_headroom(skb) - fd->offset; + } else @@ -9290,7 +9410,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + /* 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.) ++ * skbuff. Store the back-pointer inside the buffer. + */ + DPA_WRITE_SKB_PTR(skb, skbh, buffer_start, 0); + } @@ -9554,7 +9674,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + fd->length20 = skb->len; + fd->offset = priv->tx_headroom; + -+ /* DMA map the SGT page */ ++ /* DMA map the SGT page ++ * ++ * It's safe to store the skb back-pointer inside the buffer since ++ * S/G frames are non-recyclable. ++ */ + DPA_WRITE_SKB_PTR(skb, skbh, sgt_buf, 0); + addr = dma_map_single(dpa_bp->dev, sgt_buf, + priv->tx_headroom + sgt_size, @@ -9678,6 +9802,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + percpu_stats->tx_errors++; + return NETDEV_TX_OK; + } ++ ++ /* propagate the skb ownership information */ ++ if (skb->sk) ++ skb_set_owner_w(skb_new, skb->sk); ++ + dev_kfree_skb(skb); + skb = skb_new; + } @@ -11022,7 +11151,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +module_exit(dpa_ptp_unload); --- /dev/null +++ b/drivers/net/ethernet/freescale/sdk_dpaa/mac-api.c -@@ -0,0 +1,907 @@ +@@ -0,0 +1,931 @@ +/* Copyright 2008-2012 Freescale Semiconductor, Inc. + * + * Redistribution and use in source and binary forms, with or without @@ -11527,17 +11656,41 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct mac_device *mac_dev) +{ + struct phy_device *phy_dev; ++ void (*adjust_link_handler)(struct net_device *); + + if ((macdev2enetinterface(mac_dev) == e_ENET_MODE_XGMII_10000) || -+ (macdev2enetinterface(mac_dev) == e_ENET_MODE_SGMII_2500) || -+ of_phy_is_fixed_link(mac_dev->phy_node)) { -+ phy_dev = of_phy_connect(net_dev, mac_dev->phy_node, -+ &adjust_link_void, 0, -+ mac_dev->phy_if); ++ (macdev2enetinterface(mac_dev) == e_ENET_MODE_SGMII_2500)) { ++ /* Pass a void link state handler to the PHY state machine ++ * for XGMII (10G) and SGMII 2.5G, as the hardware does not ++ * permit dynamic link speed adjustments. */ ++ adjust_link_handler = adjust_link_void; ++ } else if (macdev2enetinterface(mac_dev) & e_ENET_IF_RGMII) { ++ /* Regular RGMII ports connected to a PHY, as well as ++ * ports that are marked as "fixed-link" in the DTS, ++ * will have the adjust_link callback. This calls ++ * fman_memac_adjust_link in order to configure the ++ * IF_MODE register, which is needed in both cases. ++ */ ++ adjust_link_handler = adjust_link; ++ } else if (of_phy_is_fixed_link(mac_dev->phy_node)) { ++ /* Pass a void link state handler for fixed-link ++ * interfaces that are not RGMII. Only RGMII has been ++ * tested and confirmed to work with fixed-link. Other ++ * MII interfaces may need further work. ++ * TODO: Change this as needed. ++ */ ++ adjust_link_handler = adjust_link_void; + } else { -+ phy_dev = of_phy_connect(net_dev, mac_dev->phy_node, -+ &adjust_link, 0, mac_dev->phy_if); ++ /* MII, RMII, SMII, GMII, SGMII, BASEX ports, ++ * that are NOT fixed-link. ++ * TODO: May not be needed for interfaces that ++ * pass through the SerDes block (*SGMII, XFI). ++ */ ++ adjust_link_handler = adjust_link; + } ++ phy_dev = of_phy_connect(net_dev, mac_dev->phy_node, ++ adjust_link_handler, 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", @@ -12068,10 +12221,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +static const struct of_device_id mac_match[] = { + [DTSEC] = { -+ .compatible = "fsl,fman-1g-mac" ++ .compatible = "fsl,fman-dtsec" + }, + [XGMAC] = { -+ .compatible = "fsl,fman-10g-mac" ++ .compatible = "fsl,fman-xgec" + }, + [MEMAC] = { + .compatible = "fsl,fman-memac" @@ -14929,7 +15082,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + --- /dev/null +++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/dtsec.c -@@ -0,0 +1,1465 @@ +@@ -0,0 +1,1504 @@ +/* + * Copyright 2008-2013 Freescale Semiconductor Inc. + * @@ -15318,6 +15471,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +static t_Error GracefulStop(t_Dtsec *p_Dtsec, e_CommMode mode) +{ + struct dtsec_regs *p_MemMap; ++ int pollTimeout = 0; + + ASSERT_COND(p_Dtsec); + @@ -15340,16 +15494,32 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + } + + 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 */ ++ { ++#if defined(FM_GTS_ERRATA_DTSEC_A004) ++ 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) */ ++ + fman_dtsec_stop_tx(p_MemMap); -+#endif /* FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 */ -+#endif /* defined(FM_GTS_ERRATA_DTSEC_A004) ||... */ ++ ++#if defined(FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014) || defined(FM_GTS_AFTER_MAC_ABORTED_FRAME_ERRATA_DTSEC_A0012) ++ XX_UDelay(10); ++#endif /* FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 || FM_GTS_AFTER_MAC_ABORTED_FRAME_ERRATA_DTSEC_A0012 */ ++#endif /* defined(FM_GTS_ERRATA_DTSEC_A004) */ ++ } ++ ++ /* Poll GRSC/GTSC bits in IEVENT register until both are set */ ++#if defined(FM_GRS_ERRATA_DTSEC_A002) || defined(FM_GTS_ERRATA_DTSEC_A004) || defined(FM_GTS_AFTER_MAC_ABORTED_FRAME_ERRATA_DTSEC_A0012) || defined(FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014) || defined(FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839) ++ XX_UDelay(10); ++#else ++ while (fman_dtsec_get_event(p_MemMap, DTSEC_IMASK_GRSCEN | DTSEC_IMASK_GTSCEN) != (DTSEC_IMASK_GRSCEN | DTSEC_IMASK_GTSCEN)) ++ { ++ if (pollTimeout == 100) ++ break; ++ XX_UDelay(1); ++ pollTimeout++; ++ } ++#endif + + return E_OK; +} @@ -15564,7 +15734,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + " value should be greater than 320.")); +#endif /* FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 */ + ++ GracefulStop(p_Dtsec, e_COMM_MODE_RX_AND_TX); ++ + fman_dtsec_set_tx_pause_frames(p_Dtsec->p_MemMap, pauseTime); ++ ++ GracefulRestart(p_Dtsec, e_COMM_MODE_RX_AND_TX); ++ + return E_OK; +} + @@ -15585,8 +15760,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_STATE); + SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); + ++ GracefulStop(p_Dtsec, e_COMM_MODE_RX_AND_TX); ++ + fman_dtsec_handle_rx_pause(p_Dtsec->p_MemMap, accept_pause); + ++ GracefulRestart(p_Dtsec, e_COMM_MODE_RX_AND_TX); ++ + return E_OK; +} + @@ -15719,8 +15898,13 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + /* 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); ++ ++ GracefulStop(p_Dtsec, e_COMM_MODE_RX_AND_TX); ++ + fman_dtsec_set_mac_address(p_Dtsec->p_MemMap, (uint8_t *)(*p_EnetAddr)); + ++ GracefulRestart(p_Dtsec, e_COMM_MODE_RX_AND_TX); ++ + return E_OK; +} + @@ -16008,8 +16192,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_STATE); + SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); + ++ GracefulStop(p_Dtsec, e_COMM_MODE_RX_AND_TX); ++ + fman_dtsec_set_wol(p_Dtsec->p_MemMap, en); + ++ GracefulRestart(p_Dtsec, e_COMM_MODE_RX_AND_TX); ++ + return E_OK; +} + @@ -16030,11 +16218,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + enet_speed = (enum enet_speed) ENET_SPEED_FROM_MODE(p_Dtsec->enetMode); + p_Dtsec->halfDuplex = !fullDuplex; + ++ GracefulStop(p_Dtsec, e_COMM_MODE_RX_AND_TX); ++ + 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")); + ++ GracefulRestart(p_Dtsec, e_COMM_MODE_RX_AND_TX); ++ + return (t_Error)err; +} + @@ -109906,7 +110098,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#endif /* __LNXWRP_FM_H__ */ --- /dev/null +++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm_port.c -@@ -0,0 +1,1480 @@ +@@ -0,0 +1,1512 @@ +/* + * Copyright 2008-2012 Freescale Semiconductor Inc. + * @@ -110212,7 +110404,21 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + 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 (of_device_is_compatible(port_node, "fsl,fman-port-oh") || ++ of_device_is_compatible(port_node, "fsl,fman-v2-port-oh") || ++ of_device_is_compatible(port_node, "fsl,fman-v3-port-oh")) { ++#ifndef CONFIG_FMAN_ARM ++#ifdef CONFIG_FMAN_P3040_P4080_P5020 ++ /* On PPC FMan v2, OH ports start from cell-index 0x1 */ ++ tmp_prop -= 0x1; ++#else ++ /* On PPC FMan v3 (Low and High), OH ports start from ++ * cell-index 0x2 ++ */ ++ tmp_prop -= 0x2; ++#endif // CONFIG_FMAN_P3040_P4080_P5020 ++#endif // CONFIG_FMAN_ARM ++ + if (unlikely(tmp_prop >= FM_MAX_NUM_OF_OH_PORTS)) { + REPORT_ERROR(MAJOR, E_INVALID_VALUE, + ("of_get_property(%s, cell-index) failed", @@ -110297,7 +110503,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + settings.param.specificParams.nonRxParams.qmChannel = + p_LnxWrpFmPortDev->txCh; + } else if (of_device_is_compatible(port_node, "fsl,fman-port-10g-tx")) { ++#ifndef CONFIG_FMAN_ARM ++ /* On T102x, the 10G TX port IDs start from 0x28 */ ++ if (IS_T1023_T1024) ++ tmp_prop -= 0x28; ++ else ++#endif + tmp_prop -= 0x30; ++ + if (unlikely(tmp_prop>= FM_MAX_NUM_OF_10G_TX_PORTS)) { + REPORT_ERROR(MAJOR, E_INVALID_VALUE, + ("of_get_property(%s, cell-index) failed", @@ -110308,7 +110521,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + FM_MAX_NUM_OF_1G_TX_PORTS]; +#ifndef CONFIG_FMAN_ARM + if (IS_T1023_T1024) -+ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->txPorts[*uint32_prop]; ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->txPorts[tmp_prop]; +#endif + + p_LnxWrpFmPortDev->id = tmp_prop; @@ -110346,7 +110559,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + if (p_LnxWrpFmDev->pcdActive) + p_LnxWrpFmPortDev->defPcd = p_LnxWrpFmDev->defPcd; + } else if (of_device_is_compatible(port_node, "fsl,fman-port-10g-rx")) { ++#ifndef CONFIG_FMAN_ARM ++ /* On T102x, the 10G RX port IDs start from 0x08 */ ++ if (IS_T1023_T1024) ++ tmp_prop -= 0x8; ++ else ++#endif + tmp_prop -= 0x10; ++ + if (unlikely(tmp_prop >= FM_MAX_NUM_OF_10G_RX_PORTS)) { + REPORT_ERROR(MAJOR, E_INVALID_VALUE, + ("of_get_property(%s, cell-index) failed", @@ -110358,7 +110578,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +#ifndef CONFIG_FMAN_ARM + if (IS_T1023_T1024) -+ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->rxPorts[*uint32_prop]; ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->rxPorts[tmp_prop]; +#endif + + p_LnxWrpFmPortDev->id = tmp_prop; @@ -110546,7 +110766,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + 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 != @@ -110580,7 +110800,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + 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)be32_to_cpu(uint32_prop[0]); + p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_tcp_port_filtering = @@ -110588,7 +110808,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_udp_port_filtering = + (uint16_t)be32_to_cpu(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); @@ -111328,6 +111548,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + { + .compatible = "fsl,fman-port-oh"}, + { ++ .compatible = "fsl,fman-v2-port-oh"}, ++ { ++ .compatible = "fsl,fman-v3-port-oh"}, ++ { + .compatible = "fsl,fman-port-1g-rx"}, + { + .compatible = "fsl,fman-port-10g-rx"}, @@ -135739,7 +135963,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#endif --- /dev/null +++ b/drivers/staging/fsl_qbman/qman_high.c -@@ -0,0 +1,5669 @@ +@@ -0,0 +1,5652 @@ +/* Copyright 2008-2012 Freescale Semiconductor, Inc. + * + * Redistribution and use in source and binary forms, with or without @@ -138817,36 +139041,19 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct completion completion; +}; + -+static int qman_delete_cgr_thread(void *p) ++static void qman_delete_cgr_smp_call(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; ++ qman_delete_cgr((struct qman_cgr *)p); +} + +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; -+ } ++ smp_call_function_single(qman_cgr_cpus[cgr->cgrid], ++ qman_delete_cgr_smp_call, cgr, true); ++ preempt_enable(); ++ return; + } + qman_delete_cgr(cgr); + preempt_enable(); @@ -144756,7 +144963,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#endif /* FSL_BMAN_H */ --- /dev/null +++ b/include/linux/fsl_qman.h -@@ -0,0 +1,3888 @@ +@@ -0,0 +1,3900 @@ +/* Copyright 2008-2012 Freescale Semiconductor, Inc. + * + * Redistribution and use in source and binary forms, with or without @@ -148572,6 +148779,18 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct qm_mcr_ceetm_lfqmt_query *lfqmt_query); + +/** ++ * qman_ceetm_query_cq - Queries a CEETM CQ ++ * @cqid: the channel ID (first byte) followed by the CQ idx ++ * @dcpid: CEETM portal ID ++ * @cq_query: storage for the queried CQ fields ++ * ++ * Returns zero for success or -EIO if the query command returns error. ++ * ++*/ ++int qman_ceetm_query_cq(unsigned int cqid, unsigned int dcpid, ++ struct qm_mcr_ceetm_cq_query *cq_query); ++ ++/** + * qman_ceetm_query_write_statistics - Query (and optionally write) statistics + * @cid: Target ID (CQID or CCGRID) + * @dcp_idx: CEETM portal ID diff --git a/target/linux/layerscape/patches-4.9/702-pci-support-layerscape.patch b/target/linux/layerscape/patches-4.9/702-pci-support-layerscape.patch index 03c3fb7cb9..2272a23f46 100644 --- a/target/linux/layerscape/patches-4.9/702-pci-support-layerscape.patch +++ b/target/linux/layerscape/patches-4.9/702-pci-support-layerscape.patch @@ -1,7 +1,7 @@ -From 5fcb42fbd224e1103bacbae4785745842cfd6304 Mon Sep 17 00:00:00 2001 +From b2ee6e29bad31facbbf5ac1ce98235ac163d9fa9 Mon Sep 17 00:00:00 2001 From: Yangbo Lu <yangbo.lu@nxp.com> -Date: Wed, 17 Jan 2018 15:00:43 +0800 -Subject: [PATCH 08/30] pci: support layerscape +Date: Thu, 5 Jul 2018 16:26:47 +0800 +Subject: [PATCH 08/32] pci: support layerscape This is an integrated patch for layerscape pcie support. @@ -15,19 +15,19 @@ Signed-off-by: Mingkai Hu <mingkai.hu@nxp.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- - drivers/irqchip/irq-ls-scfg-msi.c | 257 +++++++-- + drivers/irqchip/irq-ls-scfg-msi.c | 257 ++++++- drivers/pci/host/Makefile | 2 +- - drivers/pci/host/pci-layerscape-ep-debugfs.c | 758 +++++++++++++++++++++++++++ - drivers/pci/host/pci-layerscape-ep.c | 309 +++++++++++ - drivers/pci/host/pci-layerscape-ep.h | 115 ++++ + drivers/pci/host/pci-layerscape-ep-debugfs.c | 758 +++++++++++++++++++ + drivers/pci/host/pci-layerscape-ep.c | 309 ++++++++ + drivers/pci/host/pci-layerscape-ep.h | 115 +++ drivers/pci/host/pci-layerscape.c | 48 +- drivers/pci/host/pcie-designware.c | 6 + drivers/pci/host/pcie-designware.h | 1 + drivers/pci/pci.c | 2 +- - drivers/pci/pcie/portdrv_core.c | 181 +++---- - drivers/pci/quirks.c | 8 + + drivers/pci/pcie/portdrv_core.c | 181 ++--- + drivers/pci/quirks.c | 15 + include/linux/pci.h | 1 + - 12 files changed, 1539 insertions(+), 149 deletions(-) + 12 files changed, 1546 insertions(+), 149 deletions(-) create mode 100644 drivers/pci/host/pci-layerscape-ep-debugfs.c create mode 100644 drivers/pci/host/pci-layerscape-ep.c create mode 100644 drivers/pci/host/pci-layerscape-ep.h @@ -2060,7 +2060,21 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> } --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c -@@ -4679,3 +4679,11 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_IN +@@ -3329,6 +3329,13 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_A + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003c, quirk_no_bus_reset); + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0033, quirk_no_bus_reset); + ++/* ++ * NXP (Freescale Vendor ID) LS1088 chips do not behave correctly after ++ * bus reset. Link state of device does not comes UP and so config space ++ * never accessible again. ++ */ ++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_FREESCALE, 0x80c0, quirk_no_bus_reset); ++ + static void quirk_no_pm_reset(struct pci_dev *dev) + { + /* +@@ -4679,3 +4686,11 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_IN DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2031, quirk_no_aersid); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2032, quirk_no_aersid); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2033, quirk_no_aersid); diff --git a/target/linux/layerscape/patches-4.9/704-fsl-mc-layerscape-support.patch b/target/linux/layerscape/patches-4.9/704-fsl-mc-layerscape-support.patch index f6d515ada0..52c099203c 100644 --- a/target/linux/layerscape/patches-4.9/704-fsl-mc-layerscape-support.patch +++ b/target/linux/layerscape/patches-4.9/704-fsl-mc-layerscape-support.patch @@ -1,7 +1,7 @@ -From 667f0792b6f6d000c10f21c29c397c84cbe77f4a Mon Sep 17 00:00:00 2001 +From ab7b47676f9334bb55f80e0ac096c7aa289810e2 Mon Sep 17 00:00:00 2001 From: Yangbo Lu <yangbo.lu@nxp.com> -Date: Wed, 17 Jan 2018 15:11:45 +0800 -Subject: [PATCH 10/30] fsl-mc: layerscape support +Date: Thu, 5 Jul 2018 16:44:34 +0800 +Subject: [PATCH 10/32] fsl-mc: layerscape support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -19,187 +19,7533 @@ Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com> Signed-off-by: Horia Geantă <horia.geanta@nxp.com> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- - drivers/staging/fsl-mc/bus/Kconfig | 41 +- - drivers/staging/fsl-mc/bus/Makefile | 10 +- - drivers/staging/fsl-mc/bus/dpbp-cmd.h | 80 ++ - drivers/staging/fsl-mc/bus/dpbp.c | 450 +-------- - drivers/staging/fsl-mc/bus/dpcon-cmd.h | 85 ++ - drivers/staging/fsl-mc/bus/dpcon.c | 317 ++++++ - drivers/staging/fsl-mc/bus/dpio/Makefile | 11 + - .../{include/dpcon-cmd.h => bus/dpio/dpio-cmd.h} | 73 +- - drivers/staging/fsl-mc/bus/dpio/dpio-driver.c | 296 ++++++ - drivers/staging/fsl-mc/bus/dpio/dpio-service.c | 693 +++++++++++++ - drivers/staging/fsl-mc/bus/dpio/dpio.c | 224 +++++ - drivers/staging/fsl-mc/bus/dpio/dpio.h | 109 ++ - drivers/staging/fsl-mc/bus/dpio/qbman-portal.c | 1049 ++++++++++++++++++++ - drivers/staging/fsl-mc/bus/dpio/qbman-portal.h | 662 ++++++++++++ - drivers/staging/fsl-mc/bus/dpio/qbman_debug.c | 853 ++++++++++++++++ - drivers/staging/fsl-mc/bus/dpio/qbman_debug.h | 136 +++ - drivers/staging/fsl-mc/bus/dpio/qbman_private.h | 171 ++++ - drivers/staging/fsl-mc/bus/dpmcp-cmd.h | 112 +-- - drivers/staging/fsl-mc/bus/dpmcp.c | 374 +------ - drivers/staging/fsl-mc/bus/dpmcp.h | 127 +-- - drivers/staging/fsl-mc/bus/dpmng-cmd.h | 14 +- - drivers/staging/fsl-mc/bus/dpmng.c | 37 +- - drivers/staging/fsl-mc/bus/dprc-cmd.h | 82 +- - drivers/staging/fsl-mc/bus/dprc-driver.c | 38 +- - drivers/staging/fsl-mc/bus/dprc.c | 629 +----------- - drivers/staging/fsl-mc/bus/fsl-mc-allocator.c | 78 +- - drivers/staging/fsl-mc/bus/fsl-mc-bus.c | 318 +++--- - drivers/staging/fsl-mc/bus/fsl-mc-iommu.c | 104 ++ - drivers/staging/fsl-mc/bus/fsl-mc-msi.c | 2 +- - drivers/staging/fsl-mc/bus/fsl-mc-private.h | 6 +- - .../staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c | 10 +- - drivers/staging/fsl-mc/bus/mc-io.c | 4 +- - drivers/staging/fsl-mc/bus/mc-ioctl.h | 22 + - drivers/staging/fsl-mc/bus/mc-restool.c | 405 ++++++++ - drivers/staging/fsl-mc/bus/mc-sys.c | 14 +- - drivers/staging/fsl-mc/include/dpaa2-fd.h | 706 +++++++++++++ - drivers/staging/fsl-mc/include/dpaa2-global.h | 202 ++++ - drivers/staging/fsl-mc/include/dpaa2-io.h | 190 ++++ - drivers/staging/fsl-mc/include/dpbp-cmd.h | 185 ---- - drivers/staging/fsl-mc/include/dpbp.h | 158 +-- - drivers/staging/fsl-mc/include/dpcon.h | 115 +++ - drivers/staging/fsl-mc/include/dpmng.h | 16 +- - drivers/staging/fsl-mc/include/dpopr.h | 110 ++ - drivers/staging/fsl-mc/include/dprc.h | 470 +++------ - drivers/staging/fsl-mc/include/mc-bus.h | 7 +- - drivers/staging/fsl-mc/include/mc-cmd.h | 44 +- - drivers/staging/fsl-mc/include/mc-sys.h | 3 +- - drivers/staging/fsl-mc/include/mc.h | 17 +- - 48 files changed, 7247 insertions(+), 2612 deletions(-) - create mode 100644 drivers/staging/fsl-mc/bus/dpbp-cmd.h - create mode 100644 drivers/staging/fsl-mc/bus/dpcon-cmd.h - create mode 100644 drivers/staging/fsl-mc/bus/dpcon.c + Documentation/ABI/stable/sysfs-bus-fsl-mc | 13 + + Documentation/ioctl/ioctl-number.txt | 1 + + Documentation/networking/dpaa2/index.rst | 8 + + Documentation/networking/dpaa2/overview.rst | 408 +++++ + MAINTAINERS | 11 +- + drivers/bus/Kconfig | 3 + + drivers/bus/Makefile | 4 + + drivers/bus/fsl-mc/Kconfig | 23 + + drivers/bus/fsl-mc/Makefile | 22 + + drivers/bus/fsl-mc/dpbp.c | 186 +++ + drivers/bus/fsl-mc/dpcon.c | 222 +++ + drivers/bus/fsl-mc/dpmcp.c | 99 ++ + .../fsl-mc/bus => bus/fsl-mc}/dprc-driver.c | 180 ++- + drivers/bus/fsl-mc/dprc.c | 575 +++++++ + .../bus => bus/fsl-mc}/fsl-mc-allocator.c | 195 ++- + .../fsl-mc/bus => bus/fsl-mc}/fsl-mc-bus.c | 523 +++++-- + drivers/bus/fsl-mc/fsl-mc-iommu.c | 78 + + .../fsl-mc/bus => bus/fsl-mc}/fsl-mc-msi.c | 34 +- + drivers/bus/fsl-mc/fsl-mc-private.h | 223 +++ + drivers/bus/fsl-mc/fsl-mc-restool.c | 219 +++ + .../fsl-mc/bus => bus/fsl-mc}/mc-io.c | 80 +- + .../fsl-mc/bus => bus/fsl-mc}/mc-sys.c | 105 +- + drivers/irqchip/Kconfig | 6 + + drivers/irqchip/Makefile | 1 + + .../irq-gic-v3-its-fsl-mc-msi.c | 52 +- + drivers/staging/fsl-mc/Kconfig | 1 + + drivers/staging/fsl-mc/Makefile | 1 + + drivers/staging/fsl-mc/TODO | 18 - + drivers/staging/fsl-mc/bus/Kconfig | 37 +- + drivers/staging/fsl-mc/bus/Makefile | 17 +- + drivers/staging/fsl-mc/bus/dpbp.c | 691 -------- + drivers/staging/fsl-mc/bus/dpio/Makefile | 8 + + drivers/staging/fsl-mc/bus/dpio/dpio-cmd.h | 50 + + drivers/staging/fsl-mc/bus/dpio/dpio-driver.c | 278 ++++ + .../staging/fsl-mc/bus/dpio/dpio-service.c | 780 +++++++++ + drivers/staging/fsl-mc/bus/dpio/dpio.c | 221 +++ + drivers/staging/fsl-mc/bus/dpio/dpio.h | 87 ++ + .../staging/fsl-mc/bus/dpio/qbman-portal.c | 1164 ++++++++++++++ + .../staging/fsl-mc/bus/dpio/qbman-portal.h | 505 ++++++ + drivers/staging/fsl-mc/bus/dpmcp-cmd.h | 140 -- + drivers/staging/fsl-mc/bus/dpmcp.c | 504 ------ + drivers/staging/fsl-mc/bus/dpmcp.h | 159 -- + drivers/staging/fsl-mc/bus/dpmng-cmd.h | 58 - + drivers/staging/fsl-mc/bus/dpmng.c | 107 -- + drivers/staging/fsl-mc/bus/dprc-cmd.h | 465 ------ + drivers/staging/fsl-mc/bus/dprc.c | 1388 ----------------- + drivers/staging/fsl-mc/bus/fsl-mc-private.h | 52 - + drivers/staging/fsl-mc/include/dpaa2-fd.h | 681 ++++++++ + drivers/staging/fsl-mc/include/dpaa2-global.h | 177 +++ + drivers/staging/fsl-mc/include/dpaa2-io.h | 178 +++ + drivers/staging/fsl-mc/include/dpbp-cmd.h | 185 --- + drivers/staging/fsl-mc/include/dpbp.h | 220 --- + drivers/staging/fsl-mc/include/dpcon-cmd.h | 62 - + drivers/staging/fsl-mc/include/dpmng.h | 69 - + drivers/staging/fsl-mc/include/dpopr.h | 112 ++ + drivers/staging/fsl-mc/include/dprc.h | 544 ------- + drivers/staging/fsl-mc/include/mc-bus.h | 111 -- + drivers/staging/fsl-mc/include/mc-cmd.h | 108 -- + drivers/staging/fsl-mc/include/mc-sys.h | 98 -- + drivers/staging/fsl-mc/include/mc.h | 201 --- + include/linux/fsl/mc.h | 1025 ++++++++++++ + include/uapi/linux/fsl_mc.h | 31 + + 62 files changed, 8068 insertions(+), 5736 deletions(-) + create mode 100644 Documentation/ABI/stable/sysfs-bus-fsl-mc + create mode 100644 Documentation/networking/dpaa2/index.rst + create mode 100644 Documentation/networking/dpaa2/overview.rst + create mode 100644 drivers/bus/fsl-mc/Kconfig + create mode 100644 drivers/bus/fsl-mc/Makefile + create mode 100644 drivers/bus/fsl-mc/dpbp.c + create mode 100644 drivers/bus/fsl-mc/dpcon.c + create mode 100644 drivers/bus/fsl-mc/dpmcp.c + rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dprc-driver.c (84%) + create mode 100644 drivers/bus/fsl-mc/dprc.c + rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-allocator.c (71%) + rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-bus.c (64%) + create mode 100644 drivers/bus/fsl-mc/fsl-mc-iommu.c + rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-msi.c (89%) + create mode 100644 drivers/bus/fsl-mc/fsl-mc-private.h + create mode 100644 drivers/bus/fsl-mc/fsl-mc-restool.c + rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/mc-io.c (68%) + rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/mc-sys.c (66%) + rename drivers/{staging/fsl-mc/bus => irqchip}/irq-gic-v3-its-fsl-mc-msi.c (60%) + delete mode 100644 drivers/staging/fsl-mc/TODO + delete mode 100644 drivers/staging/fsl-mc/bus/dpbp.c create mode 100644 drivers/staging/fsl-mc/bus/dpio/Makefile - rename drivers/staging/fsl-mc/{include/dpcon-cmd.h => bus/dpio/dpio-cmd.h} (64%) + create mode 100644 drivers/staging/fsl-mc/bus/dpio/dpio-cmd.h create mode 100644 drivers/staging/fsl-mc/bus/dpio/dpio-driver.c create mode 100644 drivers/staging/fsl-mc/bus/dpio/dpio-service.c create mode 100644 drivers/staging/fsl-mc/bus/dpio/dpio.c create mode 100644 drivers/staging/fsl-mc/bus/dpio/dpio.h create mode 100644 drivers/staging/fsl-mc/bus/dpio/qbman-portal.c create mode 100644 drivers/staging/fsl-mc/bus/dpio/qbman-portal.h - create mode 100644 drivers/staging/fsl-mc/bus/dpio/qbman_debug.c - create mode 100644 drivers/staging/fsl-mc/bus/dpio/qbman_debug.h - create mode 100644 drivers/staging/fsl-mc/bus/dpio/qbman_private.h - create mode 100644 drivers/staging/fsl-mc/bus/fsl-mc-iommu.c - create mode 100644 drivers/staging/fsl-mc/bus/mc-ioctl.h - create mode 100644 drivers/staging/fsl-mc/bus/mc-restool.c + delete mode 100644 drivers/staging/fsl-mc/bus/dpmcp-cmd.h + delete mode 100644 drivers/staging/fsl-mc/bus/dpmcp.c + delete mode 100644 drivers/staging/fsl-mc/bus/dpmcp.h + delete mode 100644 drivers/staging/fsl-mc/bus/dpmng-cmd.h + delete mode 100644 drivers/staging/fsl-mc/bus/dpmng.c + delete mode 100644 drivers/staging/fsl-mc/bus/dprc-cmd.h + delete mode 100644 drivers/staging/fsl-mc/bus/dprc.c + delete mode 100644 drivers/staging/fsl-mc/bus/fsl-mc-private.h create mode 100644 drivers/staging/fsl-mc/include/dpaa2-fd.h create mode 100644 drivers/staging/fsl-mc/include/dpaa2-global.h create mode 100644 drivers/staging/fsl-mc/include/dpaa2-io.h delete mode 100644 drivers/staging/fsl-mc/include/dpbp-cmd.h - create mode 100644 drivers/staging/fsl-mc/include/dpcon.h + delete mode 100644 drivers/staging/fsl-mc/include/dpbp.h + delete mode 100644 drivers/staging/fsl-mc/include/dpcon-cmd.h + delete mode 100644 drivers/staging/fsl-mc/include/dpmng.h create mode 100644 drivers/staging/fsl-mc/include/dpopr.h + delete mode 100644 drivers/staging/fsl-mc/include/dprc.h + delete mode 100644 drivers/staging/fsl-mc/include/mc-bus.h + delete mode 100644 drivers/staging/fsl-mc/include/mc-cmd.h + delete mode 100644 drivers/staging/fsl-mc/include/mc-sys.h + delete mode 100644 drivers/staging/fsl-mc/include/mc.h + create mode 100644 include/linux/fsl/mc.h + create mode 100644 include/uapi/linux/fsl_mc.h ---- a/drivers/staging/fsl-mc/bus/Kconfig -+++ b/drivers/staging/fsl-mc/bus/Kconfig -@@ -1,25 +1,40 @@ - # --# Freescale Management Complex (MC) bus drivers +--- /dev/null ++++ b/Documentation/ABI/stable/sysfs-bus-fsl-mc +@@ -0,0 +1,13 @@ ++What: /sys/bus/fsl-mc/devices/dprc.*/rescan ++Date: March. 2018 ++KernelVersion: 4.16 ++Contact: Ioana Ciornei <ioana.ciornei@nxp.com> ++Description: Root dprc rescan attribute ++Users: Userspace drivers and management tools ++ ++What: /sys/bus/fsl-mc/rescan ++Date: March. 2018 ++KernelVersion: 4.16 ++Contact: Ioana Ciornei <ioana.ciornei@nxp.com> ++Description: Bus rescan attribute ++Users: Userspace drivers and management tools +--- a/Documentation/ioctl/ioctl-number.txt ++++ b/Documentation/ioctl/ioctl-number.txt +@@ -170,6 +170,7 @@ Code Seq#(hex) Include File Comments + 'R' 00-1F linux/random.h conflict! + 'R' 01 linux/rfkill.h conflict! + 'R' C0-DF net/bluetooth/rfcomm.h ++'R' E0 uapi/linux/fsl_mc.h + 'S' all linux/cdrom.h conflict! + 'S' 80-81 scsi/scsi_ioctl.h conflict! + 'S' 82-FF scsi/scsi.h conflict! +--- /dev/null ++++ b/Documentation/networking/dpaa2/index.rst +@@ -0,0 +1,8 @@ ++=================== ++DPAA2 Documentation ++=================== ++ ++.. toctree:: ++ :maxdepth: 1 ++ ++ overview +--- /dev/null ++++ b/Documentation/networking/dpaa2/overview.rst +@@ -0,0 +1,408 @@ ++.. include:: <isonum.txt> ++ ++DPAA2 (Data Path Acceleration Architecture Gen2) Overview ++========================================================= ++ ++:Copyright: |copy| 2015 Freescale Semiconductor Inc. ++:Copyright: |copy| 2018 NXP ++ ++This document provides an overview of the Freescale DPAA2 architecture ++and how it is integrated into the Linux kernel. ++ ++Introduction ++============ ++ ++DPAA2 is a hardware architecture designed for high-speeed network ++packet processing. DPAA2 consists of sophisticated mechanisms for ++processing Ethernet packets, queue management, buffer management, ++autonomous L2 switching, virtual Ethernet bridging, and accelerator ++(e.g. crypto) sharing. ++ ++A DPAA2 hardware component called the Management Complex (or MC) manages the ++DPAA2 hardware resources. The MC provides an object-based abstraction for ++software drivers to use the DPAA2 hardware. ++The MC uses DPAA2 hardware resources such as queues, buffer pools, and ++network ports to create functional objects/devices such as network ++interfaces, an L2 switch, or accelerator instances. ++The MC provides memory-mapped I/O command interfaces (MC portals) ++which DPAA2 software drivers use to operate on DPAA2 objects. ++ ++The diagram below shows an overview of the DPAA2 resource management ++architecture:: ++ ++ +--------------------------------------+ ++ | OS | ++ | DPAA2 drivers | ++ | | | ++ +-----------------------------|--------+ ++ | ++ | (create,discover,connect ++ | config,use,destroy) ++ | ++ DPAA2 | ++ +------------------------| mc portal |-+ ++ | | | ++ | +- - - - - - - - - - - - -V- - -+ | ++ | | | | ++ | | Management Complex (MC) | | ++ | | | | ++ | +- - - - - - - - - - - - - - - -+ | ++ | | ++ | Hardware Hardware | ++ | Resources Objects | ++ | --------- ------- | ++ | -queues -DPRC | ++ | -buffer pools -DPMCP | ++ | -Eth MACs/ports -DPIO | ++ | -network interface -DPNI | ++ | profiles -DPMAC | ++ | -queue portals -DPBP | ++ | -MC portals ... | ++ | ... | ++ | | ++ +--------------------------------------+ ++ ++ ++The MC mediates operations such as create, discover, ++connect, configuration, and destroy. Fast-path operations ++on data, such as packet transmit/receive, are not mediated by ++the MC and are done directly using memory mapped regions in ++DPIO objects. ++ ++Overview of DPAA2 Objects ++========================= ++ ++The section provides a brief overview of some key DPAA2 objects. ++A simple scenario is described illustrating the objects involved ++in creating a network interfaces. ++ ++DPRC (Datapath Resource Container) ++---------------------------------- ++ ++A DPRC is a container object that holds all the other ++types of DPAA2 objects. In the example diagram below there ++are 8 objects of 5 types (DPMCP, DPIO, DPBP, DPNI, and DPMAC) ++in the container. ++ ++:: ++ ++ +---------------------------------------------------------+ ++ | DPRC | ++ | | ++ | +-------+ +-------+ +-------+ +-------+ +-------+ | ++ | | DPMCP | | DPIO | | DPBP | | DPNI | | DPMAC | | ++ | +-------+ +-------+ +-------+ +---+---+ +---+---+ | ++ | | DPMCP | | DPIO | | ++ | +-------+ +-------+ | ++ | | DPMCP | | ++ | +-------+ | ++ | | ++ +---------------------------------------------------------+ ++ ++From the point of view of an OS, a DPRC behaves similar to a plug and ++play bus, like PCI. DPRC commands can be used to enumerate the contents ++of the DPRC, discover the hardware objects present (including mappable ++regions and interrupts). ++ ++:: ++ ++ DPRC.1 (bus) ++ | ++ +--+--------+-------+-------+-------+ ++ | | | | | ++ DPMCP.1 DPIO.1 DPBP.1 DPNI.1 DPMAC.1 ++ DPMCP.2 DPIO.2 ++ DPMCP.3 ++ ++Hardware objects can be created and destroyed dynamically, providing ++the ability to hot plug/unplug objects in and out of the DPRC. ++ ++A DPRC has a mappable MMIO region (an MC portal) that can be used ++to send MC commands. It has an interrupt for status events (like ++hotplug). ++All objects in a container share the same hardware "isolation context". ++This means that with respect to an IOMMU the isolation granularity ++is at the DPRC (container) level, not at the individual object ++level. ++ ++DPRCs can be defined statically and populated with objects ++via a config file passed to the MC when firmware starts it. ++There is also a Linux user space tool called "restool" that can be ++used to create/destroy containers and objects dynamically. The latest ++version of restool can be found at: ++ https://github.com/qoriq-open-source/restool ++ ++DPAA2 Objects for an Ethernet Network Interface ++----------------------------------------------- ++ ++A typical Ethernet NIC is monolithic-- the NIC device contains TX/RX ++queuing mechanisms, configuration mechanisms, buffer management, ++physical ports, and interrupts. DPAA2 uses a more granular approach ++utilizing multiple hardware objects. Each object provides specialized ++functions. Groups of these objects are used by software to provide ++Ethernet network interface functionality. This approach provides ++efficient use of finite hardware resources, flexibility, and ++performance advantages. ++ ++The diagram below shows the objects needed for a simple ++network interface configuration on a system with 2 CPUs. ++ ++:: ++ ++ +---+---+ +---+---+ ++ CPU0 CPU1 ++ +---+---+ +---+---+ ++ | | ++ +---+---+ +---+---+ ++ DPIO DPIO ++ +---+---+ +---+---+ ++ \ / ++ \ / ++ \ / ++ +---+---+ ++ DPNI --- DPBP,DPMCP ++ +---+---+ ++ | ++ | ++ +---+---+ ++ DPMAC ++ +---+---+ ++ | ++ port/PHY ++ ++Below the objects are described. For each object a brief description ++is provided along with a summary of the kinds of operations the object ++supports and a summary of key resources of the object (MMIO regions ++and IRQs). ++ ++DPMAC (Datapath Ethernet MAC) ++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++Represents an Ethernet MAC, a hardware device that connects to an Ethernet ++PHY and allows physical transmission and reception of Ethernet frames. ++ ++- MMIO regions: none ++- IRQs: DPNI link change ++- commands: set link up/down, link config, get stats, ++ IRQ config, enable, reset ++ ++DPNI (Datapath Network Interface) ++Contains TX/RX queues, network interface configuration, and RX buffer pool ++configuration mechanisms. The TX/RX queues are in memory and are identified ++by queue number. ++ ++- MMIO regions: none ++- IRQs: link state ++- commands: port config, offload config, queue config, ++ parse/classify config, IRQ config, enable, reset ++ ++DPIO (Datapath I/O) ++~~~~~~~~~~~~~~~~~~~ ++Provides interfaces to enqueue and dequeue ++packets and do hardware buffer pool management operations. The DPAA2 ++architecture separates the mechanism to access queues (the DPIO object) ++from the queues themselves. The DPIO provides an MMIO interface to ++enqueue/dequeue packets. To enqueue something a descriptor is written ++to the DPIO MMIO region, which includes the target queue number. ++There will typically be one DPIO assigned to each CPU. This allows all ++CPUs to simultaneously perform enqueue/dequeued operations. DPIOs are ++expected to be shared by different DPAA2 drivers. ++ ++- MMIO regions: queue operations, buffer management ++- IRQs: data availability, congestion notification, buffer ++ pool depletion ++- commands: IRQ config, enable, reset ++ ++DPBP (Datapath Buffer Pool) ++~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++Represents a hardware buffer pool. ++ ++- MMIO regions: none ++- IRQs: none ++- commands: enable, reset ++ ++DPMCP (Datapath MC Portal) ++~~~~~~~~~~~~~~~~~~~~~~~~~~ ++Provides an MC command portal. ++Used by drivers to send commands to the MC to manage ++objects. ++ ++- MMIO regions: MC command portal ++- IRQs: command completion ++- commands: IRQ config, enable, reset ++ ++Object Connections ++================== ++Some objects have explicit relationships that must ++be configured: ++ ++- DPNI <--> DPMAC ++- DPNI <--> DPNI ++- DPNI <--> L2-switch-port ++ ++ A DPNI must be connected to something such as a DPMAC, ++ another DPNI, or L2 switch port. The DPNI connection ++ is made via a DPRC command. ++ ++:: ++ ++ +-------+ +-------+ ++ | DPNI | | DPMAC | ++ +---+---+ +---+---+ ++ | | ++ +==========+ ++ ++- DPNI <--> DPBP ++ ++ A network interface requires a 'buffer pool' (DPBP ++ object) which provides a list of pointers to memory ++ where received Ethernet data is to be copied. The ++ Ethernet driver configures the DPBPs associated with ++ the network interface. ++ ++Interrupts ++========== ++All interrupts generated by DPAA2 objects are message ++interrupts. At the hardware level message interrupts ++generated by devices will normally have 3 components-- ++1) a non-spoofable 'device-id' expressed on the hardware ++bus, 2) an address, 3) a data value. ++ ++In the case of DPAA2 devices/objects, all objects in the ++same container/DPRC share the same 'device-id'. ++For ARM-based SoC this is the same as the stream ID. ++ ++ ++DPAA2 Linux Drivers Overview ++============================ ++ ++This section provides an overview of the Linux kernel drivers for ++DPAA2-- 1) the bus driver and associated "DPAA2 infrastructure" ++drivers and 2) functional object drivers (such as Ethernet). ++ ++As described previously, a DPRC is a container that holds the other ++types of DPAA2 objects. It is functionally similar to a plug-and-play ++bus controller. ++Each object in the DPRC is a Linux "device" and is bound to a driver. ++The diagram below shows the Linux drivers involved in a networking ++scenario and the objects bound to each driver. A brief description ++of each driver follows. ++ ++:: ++ ++ +------------+ ++ | OS Network | ++ | Stack | ++ +------------+ +------------+ ++ | Allocator |. . . . . . . | Ethernet | ++ |(DPMCP,DPBP)| | (DPNI) | ++ +-.----------+ +---+---+----+ ++ . . ^ | ++ . . <data avail, | | <enqueue, ++ . . tx confirm> | | dequeue> ++ +-------------+ . | | ++ | DPRC driver | . +---+---V----+ +---------+ ++ | (DPRC) | . . . . . .| DPIO driver| | MAC | ++ +----------+--+ | (DPIO) | | (DPMAC) | ++ | +------+-----+ +-----+---+ ++ |<dev add/remove> | | ++ | | | ++ +--------+----------+ | +--+---+ ++ | MC-bus driver | | | PHY | ++ | | | |driver| ++ | /bus/fsl-mc | | +--+---+ ++ +-------------------+ | | ++ | | ++ ========================= HARDWARE =========|=================|====== ++ DPIO | ++ | | ++ DPNI---DPBP | ++ | | ++ DPMAC | ++ | | ++ PHY ---------------+ ++ ============================================|======================== ++ ++A brief description of each driver is provided below. ++ ++MC-bus driver ++------------- ++The MC-bus driver is a platform driver and is probed from a ++node in the device tree (compatible "fsl,qoriq-mc") passed in by boot ++firmware. It is responsible for bootstrapping the DPAA2 kernel ++infrastructure. ++Key functions include: ++ ++- registering a new bus type named "fsl-mc" with the kernel, ++ and implementing bus call-backs (e.g. match/uevent/dev_groups) ++- implementing APIs for DPAA2 driver registration and for device ++ add/remove ++- creates an MSI IRQ domain ++- doing a 'device add' to expose the 'root' DPRC, in turn triggering ++ a bind of the root DPRC to the DPRC driver ++ ++The binding for the MC-bus device-tree node can be consulted at ++*Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt*. ++The sysfs bind/unbind interfaces for the MC-bus can be consulted at ++*Documentation/ABI/testing/sysfs-bus-fsl-mc*. ++ ++DPRC driver ++----------- ++The DPRC driver is bound to DPRC objects and does runtime management ++of a bus instance. It performs the initial bus scan of the DPRC ++and handles interrupts for container events such as hot plug by ++re-scanning the DPRC. ++ ++Allocator ++--------- ++Certain objects such as DPMCP and DPBP are generic and fungible, ++and are intended to be used by other drivers. For example, ++the DPAA2 Ethernet driver needs: ++ ++- DPMCPs to send MC commands, to configure network interfaces ++- DPBPs for network buffer pools ++ ++The allocator driver registers for these allocatable object types ++and those objects are bound to the allocator when the bus is probed. ++The allocator maintains a pool of objects that are available for ++allocation by other DPAA2 drivers. ++ ++DPIO driver ++----------- ++The DPIO driver is bound to DPIO objects and provides services that allow ++other drivers such as the Ethernet driver to enqueue and dequeue data for ++their respective objects. ++Key services include: ++ ++- data availability notifications ++- hardware queuing operations (enqueue and dequeue of data) ++- hardware buffer pool management ++ ++To transmit a packet the Ethernet driver puts data on a queue and ++invokes a DPIO API. For receive, the Ethernet driver registers ++a data availability notification callback. To dequeue a packet ++a DPIO API is used. ++There is typically one DPIO object per physical CPU for optimum ++performance, allowing different CPUs to simultaneously enqueue ++and dequeue data. ++ ++The DPIO driver operates on behalf of all DPAA2 drivers ++active in the kernel-- Ethernet, crypto, compression, ++etc. ++ ++Ethernet driver ++--------------- ++The Ethernet driver is bound to a DPNI and implements the kernel ++interfaces needed to connect the DPAA2 network interface to ++the network stack. ++Each DPNI corresponds to a Linux network interface. ++ ++MAC driver ++---------- ++An Ethernet PHY is an off-chip, board specific component and is managed ++by the appropriate PHY driver via an mdio bus. The MAC driver ++plays a role of being a proxy between the PHY driver and the ++MC. It does this proxy via the MC commands to a DPMAC object. ++If the PHY driver signals a link change, the MAC driver notifies ++the MC via a DPMAC command. If a network interface is brought ++up or down, the MC notifies the DPMAC driver via an interrupt and ++the driver can take appropriate action. +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -3980,6 +3980,12 @@ S: Maintained + F: drivers/char/dtlk.c + F: include/linux/dtlk.h + ++DPAA2 DATAPATH I/O (DPIO) DRIVER ++M: Roy Pledge <Roy.Pledge@nxp.com> ++L: linux-kernel@vger.kernel.org ++S: Maintained ++F: drivers/staging/fsl-mc/bus/dpio ++ + DPT_I2O SCSI RAID DRIVER + M: Adaptec OEM Raid Solutions <aacraid@adaptec.com> + L: linux-scsi@vger.kernel.org +@@ -5110,7 +5116,10 @@ M: "J. German Rivera" <German.Rivera@fre + M: Stuart Yoder <stuart.yoder@nxp.com> + L: linux-kernel@vger.kernel.org + S: Maintained +-F: drivers/staging/fsl-mc/ ++F: drivers/bus/fsl-mc/ ++F: Documentation/networking/dpaa2/overview.rst ++F: include/uapi/linux/fsl_mc.h ++F: Documentation/ABI/stable/sysfs-bus-fsl-mc + + FREEVXFS FILESYSTEM + M: Christoph Hellwig <hch@infradead.org> +--- a/drivers/bus/Kconfig ++++ b/drivers/bus/Kconfig +@@ -167,4 +167,7 @@ config VEXPRESS_CONFIG + help + Platform configuration infrastructure for the ARM Ltd. + Versatile Express. ++ ++source "drivers/bus/fsl-mc/Kconfig" ++ + endmenu +--- a/drivers/bus/Makefile ++++ b/drivers/bus/Makefile +@@ -7,6 +7,10 @@ obj-$(CONFIG_ARM_CCI) += arm-cci.o + obj-$(CONFIG_ARM_CCN) += arm-ccn.o + + obj-$(CONFIG_BRCMSTB_GISB_ARB) += brcmstb_gisb.o ++ +# DPAA2 fsl-mc bus - # --# Copyright (C) 2014 Freescale Semiconductor, Inc. ++obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/ ++ + obj-$(CONFIG_IMX_WEIM) += imx-weim.o + obj-$(CONFIG_MIPS_CDMM) += mips_cdmm.o + obj-$(CONFIG_MVEBU_MBUS) += mvebu-mbus.o +--- /dev/null ++++ b/drivers/bus/fsl-mc/Kconfig +@@ -0,0 +1,23 @@ ++# SPDX-License-Identifier: GPL-2.0 ++# ++# DPAA2 fsl-mc bus ++# +# Copyright (C) 2014-2016 Freescale Semiconductor, Inc. - # - # This file is released under the GPLv2 - # - - config FSL_MC_BUS -- bool "Freescale Management Complex (MC) bus driver" -- depends on OF && ARM64 ++# ++ ++config FSL_MC_BUS + bool "QorIQ DPAA2 fsl-mc bus driver" -+ depends on OF && ARCH_LAYERSCAPE - select GENERIC_MSI_IRQ_DOMAIN - help -- Driver to enable the bus infrastructure for the Freescale -- QorIQ Management Complex (fsl-mc). The fsl-mc is a hardware -- module of the QorIQ LS2 SoCs, that does resource management -- for hardware building-blocks in the SoC that can be used -- to dynamically create networking hardware objects such as -- network interfaces (NICs), crypto accelerator instances, -- or L2 switches. ++ depends on OF && (ARCH_LAYERSCAPE || (COMPILE_TEST && (ARM || ARM64 || X86 || PPC))) ++ select GENERIC_MSI_IRQ_DOMAIN ++ help + Driver to enable the bus infrastructure for the QorIQ DPAA2 + architecture. The fsl-mc bus driver handles discovery of + DPAA2 objects (which are represented as Linux devices) and + binding objects to drivers. - -- Only enable this option when building the kernel for -- Freescale QorQIQ LS2xxxx SoCs. -+config FSL_MC_DPIO -+ tristate "QorIQ DPAA2 DPIO driver" -+ depends on FSL_MC_BUS -+ help -+ Driver for the DPAA2 DPIO object. A DPIO provides queue and -+ buffer management facilities for software to interact with -+ other DPAA2 objects. This driver does not expose the DPIO -+ objects individually, but groups them under a service layer -+ API. - -+config FSL_QBMAN_DEBUG -+ tristate "Freescale QBMAN Debug APIs" -+ depends on FSL_MC_DPIO -+ help -+ QBMan debug assistant APIs. - ++ +config FSL_MC_RESTOOL -+ tristate "Freescale Management Complex (MC) restool driver" -+ depends on FSL_MC_BUS -+ help -+ Driver that provides kernel support for the Freescale Management -+ Complex resource manager user-space tool. ---- a/drivers/staging/fsl-mc/bus/Makefile -+++ b/drivers/staging/fsl-mc/bus/Makefile -@@ -17,4 +17,12 @@ mc-bus-driver-objs := fsl-mc-bus.o \ - fsl-mc-msi.o \ - irq-gic-v3-its-fsl-mc-msi.o \ - dpmcp.o \ -- dpbp.o ++ bool "Management Complex (MC) restool support" ++ depends on FSL_MC_BUS ++ help ++ Provides kernel support for the Management Complex resource ++ manager user-space tool - restool. +--- /dev/null ++++ b/drivers/bus/fsl-mc/Makefile +@@ -0,0 +1,22 @@ ++# SPDX-License-Identifier: GPL-2.0 ++# ++# Freescale Management Complex (MC) bus drivers ++# ++# Copyright (C) 2014 Freescale Semiconductor, Inc. ++# ++obj-$(CONFIG_FSL_MC_BUS) += mc-bus-driver.o ++ ++mc-bus-driver-objs := fsl-mc-bus.o \ ++ mc-sys.o \ ++ mc-io.o \ + dpbp.o \ + dpcon.o \ ++ dprc.o \ ++ dprc-driver.o \ ++ fsl-mc-allocator.o \ ++ fsl-mc-msi.o \ ++ dpmcp.o \ + fsl-mc-iommu.o + -+# MC DPIO driver -+obj-$(CONFIG_FSL_MC_DPIO) += dpio/ -+ +# MC restool kernel support -+obj-$(CONFIG_FSL_MC_RESTOOL) += mc-restool.o ++obj-$(CONFIG_FSL_MC_RESTOOL) += fsl-mc-restool.o --- /dev/null -+++ b/drivers/staging/fsl-mc/bus/dpbp-cmd.h -@@ -0,0 +1,80 @@ ++++ b/drivers/bus/fsl-mc/dpbp.c +@@ -0,0 +1,186 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright 2013-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 the above-listed copyright holders nor the -+ * names of any contributors may be used to endorse or promote products -+ * derived from this software without specific prior written permission. ++ */ ++#include <linux/kernel.h> ++#include <linux/fsl/mc.h> ++#include <linux/fsl/mc.h> ++ ++#include "fsl-mc-private.h" ++ ++/** ++ * dpbp_open() - Open a control session for the specified object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpbp_id: DPBP unique ID ++ * @token: Returned token; use in subsequent API calls + * -+ * 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 function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpbp_create function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object + * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_open(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ int dpbp_id, ++ u16 *token) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ struct dpbp_cmd_open *cmd_params; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN, ++ cmd_flags, 0); ++ cmd_params = (struct dpbp_cmd_open *)cmd.params; ++ cmd_params->dpbp_id = cpu_to_le32(dpbp_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = mc_cmd_hdr_read_token(&cmd); ++ ++ return err; ++} ++EXPORT_SYMBOL_GPL(dpbp_open); ++ ++/** ++ * dpbp_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_close(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++EXPORT_SYMBOL_GPL(dpbp_close); ++ ++/** ++ * dpbp_enable() - Enable the DPBP. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_enable(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++EXPORT_SYMBOL_GPL(dpbp_enable); ++ ++/** ++ * dpbp_disable() - Disable the DPBP. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_disable(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE, ++ cmd_flags, token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++EXPORT_SYMBOL_GPL(dpbp_disable); ++ ++/** ++ * dpbp_reset() - Reset the DPBP, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_reset(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET, ++ cmd_flags, token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++EXPORT_SYMBOL_GPL(dpbp_reset); ++ ++/** ++ * dpbp_get_attributes - Retrieve DPBP attributes. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_get_attributes(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ struct dpbp_attr *attr) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ struct dpbp_rsp_get_attributes *rsp_params; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_ATTR, ++ cmd_flags, token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ rsp_params = (struct dpbp_rsp_get_attributes *)cmd.params; ++ attr->bpid = le16_to_cpu(rsp_params->bpid); ++ attr->id = le32_to_cpu(rsp_params->id); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(dpbp_get_attributes); +--- /dev/null ++++ b/drivers/bus/fsl-mc/dpcon.c +@@ -0,0 +1,222 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright 2013-2016 Freescale Semiconductor Inc. ++ * ++ */ ++#include <linux/kernel.h> ++#include <linux/fsl/mc.h> ++#include <linux/fsl/mc.h> ++ ++#include "fsl-mc-private.h" ++ ++/** ++ * dpcon_open() - Open a control session for the specified object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpcon_id: DPCON unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpcon_create() function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_open(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ int dpcon_id, ++ u16 *token) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ struct dpcon_cmd_open *dpcon_cmd; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ dpcon_cmd = (struct dpcon_cmd_open *)cmd.params; ++ dpcon_cmd->dpcon_id = cpu_to_le32(dpcon_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = mc_cmd_hdr_read_token(&cmd); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(dpcon_open); ++ ++/** ++ * dpcon_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_close(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_CLOSE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++EXPORT_SYMBOL_GPL(dpcon_close); ++ ++/** ++ * dpcon_enable() - Enable the DPCON ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * ++ * Return: '0' on Success; Error code otherwise ++ */ ++int dpcon_enable(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_ENABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++EXPORT_SYMBOL_GPL(dpcon_enable); ++ ++/** ++ * dpcon_disable() - Disable the DPCON ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * ++ * Return: '0' on Success; Error code otherwise ++ */ ++int dpcon_disable(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++EXPORT_SYMBOL_GPL(dpcon_disable); ++ ++/** ++ * dpcon_reset() - Reset the DPCON, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_reset(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_RESET, ++ cmd_flags, token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++EXPORT_SYMBOL_GPL(dpcon_reset); ++ ++/** ++ * dpcon_get_attributes() - Retrieve DPCON attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * @attr: Object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_get_attributes(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ struct dpcon_attr *attr) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ struct dpcon_rsp_get_attr *dpcon_rsp; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ dpcon_rsp = (struct dpcon_rsp_get_attr *)cmd.params; ++ attr->id = le32_to_cpu(dpcon_rsp->id); ++ attr->qbman_ch_id = le16_to_cpu(dpcon_rsp->qbman_ch_id); ++ attr->num_priorities = dpcon_rsp->num_priorities; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(dpcon_get_attributes); ++ ++/** ++ * dpcon_set_notification() - Set DPCON notification destination ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * @cfg: Notification parameters ++ * ++ * Return: '0' on Success; Error code otherwise ++ */ ++int dpcon_set_notification(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ struct dpcon_notification_cfg *cfg) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ struct dpcon_cmd_set_notification *dpcon_cmd; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_SET_NOTIFICATION, ++ cmd_flags, ++ token); ++ dpcon_cmd = (struct dpcon_cmd_set_notification *)cmd.params; ++ dpcon_cmd->dpio_id = cpu_to_le32(cfg->dpio_id); ++ dpcon_cmd->priority = cfg->priority; ++ dpcon_cmd->user_ctx = cpu_to_le64(cfg->user_ctx); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++EXPORT_SYMBOL_GPL(dpcon_set_notification); +--- /dev/null ++++ b/drivers/bus/fsl-mc/dpmcp.c +@@ -0,0 +1,99 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright 2013-2016 Freescale Semiconductor Inc. ++ * ++ */ ++#include <linux/kernel.h> ++#include <linux/fsl/mc.h> ++ ++#include "fsl-mc-private.h" ++ ++/** ++ * dpmcp_open() - Open a control session for the specified object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpmcp_id: DPMCP unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpmcp_create function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_open(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ int dpmcp_id, ++ u16 *token) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ struct dpmcp_cmd_open *cmd_params; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_OPEN, ++ cmd_flags, 0); ++ cmd_params = (struct dpmcp_cmd_open *)cmd.params; ++ cmd_params->dpmcp_id = cpu_to_le32(dpmcp_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = mc_cmd_hdr_read_token(&cmd); ++ ++ return err; ++} ++ ++/** ++ * dpmcp_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMCP object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_close(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CLOSE, ++ cmd_flags, token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++/** ++ * dpmcp_reset() - Reset the DPMCP, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMCP object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_reset(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_RESET, ++ cmd_flags, token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} +--- a/drivers/staging/fsl-mc/bus/dprc-driver.c ++++ /dev/null +@@ -1,805 +0,0 @@ +-/* +- * Freescale data path resource container (DPRC) driver +- * +- * Copyright (C) 2014 Freescale Semiconductor, Inc. +- * Author: German Rivera <German.Rivera@freescale.com> +- * +- * 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 <linux/module.h> +-#include <linux/slab.h> +-#include <linux/interrupt.h> +-#include <linux/msi.h> +-#include "../include/mc-bus.h" +-#include "../include/mc-sys.h" +- +-#include "dprc-cmd.h" +-#include "fsl-mc-private.h" +- +-#define FSL_MC_DPRC_DRIVER_NAME "fsl_mc_dprc" +- +-#define FSL_MC_DEVICE_MATCH(_mc_dev, _obj_desc) \ +- (strcmp((_mc_dev)->obj_desc.type, (_obj_desc)->type) == 0 && \ +- (_mc_dev)->obj_desc.id == (_obj_desc)->id) +- +-struct dprc_child_objs { +- int child_count; +- struct dprc_obj_desc *child_array; +-}; +- +-static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data) +-{ +- int i; +- struct dprc_child_objs *objs; +- struct fsl_mc_device *mc_dev; +- +- WARN_ON(!dev); +- WARN_ON(!data); +- mc_dev = to_fsl_mc_device(dev); +- objs = data; +- +- for (i = 0; i < objs->child_count; i++) { +- struct dprc_obj_desc *obj_desc = &objs->child_array[i]; +- +- if (strlen(obj_desc->type) != 0 && +- FSL_MC_DEVICE_MATCH(mc_dev, obj_desc)) +- break; +- } +- +- if (i == objs->child_count) +- fsl_mc_device_remove(mc_dev); +- +- return 0; +-} +- +-static int __fsl_mc_device_remove(struct device *dev, void *data) +-{ +- WARN_ON(!dev); +- WARN_ON(data); +- fsl_mc_device_remove(to_fsl_mc_device(dev)); +- return 0; +-} +- +-/** +- * dprc_remove_devices - Removes devices for objects removed from a DPRC +- * +- * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object +- * @obj_desc_array: array of object descriptors for child objects currently +- * present in the DPRC in the MC. +- * @num_child_objects_in_mc: number of entries in obj_desc_array +- * +- * Synchronizes the state of the Linux bus driver with the actual state of +- * the MC by removing devices that represent MC objects that have +- * been dynamically removed in the physical DPRC. +- */ +-static void dprc_remove_devices(struct fsl_mc_device *mc_bus_dev, +- struct dprc_obj_desc *obj_desc_array, +- int num_child_objects_in_mc) +-{ +- if (num_child_objects_in_mc != 0) { +- /* +- * Remove child objects that are in the DPRC in Linux, +- * but not in the MC: +- */ +- struct dprc_child_objs objs; +- +- objs.child_count = num_child_objects_in_mc; +- objs.child_array = obj_desc_array; +- device_for_each_child(&mc_bus_dev->dev, &objs, +- __fsl_mc_device_remove_if_not_in_mc); +- } else { +- /* +- * There are no child objects for this DPRC in the MC. +- * So, remove all the child devices from Linux: +- */ +- device_for_each_child(&mc_bus_dev->dev, NULL, +- __fsl_mc_device_remove); +- } +-} +- +-static int __fsl_mc_device_match(struct device *dev, void *data) +-{ +- struct dprc_obj_desc *obj_desc = data; +- struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); +- +- return FSL_MC_DEVICE_MATCH(mc_dev, obj_desc); +-} +- +-static struct fsl_mc_device *fsl_mc_device_lookup(struct dprc_obj_desc +- *obj_desc, +- struct fsl_mc_device +- *mc_bus_dev) +-{ +- struct device *dev; +- +- dev = device_find_child(&mc_bus_dev->dev, obj_desc, +- __fsl_mc_device_match); +- +- return dev ? to_fsl_mc_device(dev) : NULL; +-} +- +-/** +- * check_plugged_state_change - Check change in an MC object's plugged state +- * +- * @mc_dev: pointer to the fsl-mc device for a given MC object +- * @obj_desc: pointer to the MC object's descriptor in the MC +- * +- * If the plugged state has changed from unplugged to plugged, the fsl-mc +- * device is bound to the corresponding device driver. +- * If the plugged state has changed from plugged to unplugged, the fsl-mc +- * device is unbound from the corresponding device driver. +- */ +-static void check_plugged_state_change(struct fsl_mc_device *mc_dev, +- struct dprc_obj_desc *obj_desc) +-{ +- int error; +- u32 plugged_flag_at_mc = +- obj_desc->state & DPRC_OBJ_STATE_PLUGGED; +- +- if (plugged_flag_at_mc != +- (mc_dev->obj_desc.state & DPRC_OBJ_STATE_PLUGGED)) { +- if (plugged_flag_at_mc) { +- mc_dev->obj_desc.state |= DPRC_OBJ_STATE_PLUGGED; +- error = device_attach(&mc_dev->dev); +- if (error < 0) { +- dev_err(&mc_dev->dev, +- "device_attach() failed: %d\n", +- error); +- } +- } else { +- mc_dev->obj_desc.state &= ~DPRC_OBJ_STATE_PLUGGED; +- device_release_driver(&mc_dev->dev); +- } +- } +-} +- +-/** +- * dprc_add_new_devices - Adds devices to the logical bus for a DPRC +- * +- * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object +- * @obj_desc_array: array of device descriptors for child devices currently +- * present in the physical DPRC. +- * @num_child_objects_in_mc: number of entries in obj_desc_array +- * +- * Synchronizes the state of the Linux bus driver with the actual +- * state of the MC by adding objects that have been newly discovered +- * in the physical DPRC. +- */ +-static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev, +- struct dprc_obj_desc *obj_desc_array, +- int num_child_objects_in_mc) +-{ +- int error; +- int i; +- +- for (i = 0; i < num_child_objects_in_mc; i++) { +- struct fsl_mc_device *child_dev; +- struct dprc_obj_desc *obj_desc = &obj_desc_array[i]; +- +- if (strlen(obj_desc->type) == 0) +- continue; +- +- /* +- * Check if device is already known to Linux: +- */ +- child_dev = fsl_mc_device_lookup(obj_desc, mc_bus_dev); +- if (child_dev) { +- check_plugged_state_change(child_dev, obj_desc); +- continue; +- } +- +- error = fsl_mc_device_add(obj_desc, NULL, &mc_bus_dev->dev, +- &child_dev); +- if (error < 0) +- continue; +- } +-} +- +-/** +- * dprc_scan_objects - Discover objects in a DPRC +- * +- * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object +- * @total_irq_count: total number of IRQs needed by objects in the DPRC. +- * +- * Detects objects added and removed from a DPRC and synchronizes the +- * state of the Linux bus driver, MC by adding and removing +- * devices accordingly. +- * Two types of devices can be found in a DPRC: allocatable objects (e.g., +- * dpbp, dpmcp) and non-allocatable devices (e.g., dprc, dpni). +- * All allocatable devices needed to be probed before all non-allocatable +- * devices, to ensure that device drivers for non-allocatable +- * devices can allocate any type of allocatable devices. +- * That is, we need to ensure that the corresponding resource pools are +- * populated before they can get allocation requests from probe callbacks +- * of the device drivers for the non-allocatable devices. +- */ +-int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, +- unsigned int *total_irq_count) +-{ +- int num_child_objects; +- int dprc_get_obj_failures; +- int error; +- unsigned int irq_count = mc_bus_dev->obj_desc.irq_count; +- struct dprc_obj_desc *child_obj_desc_array = NULL; +- +- error = dprc_get_obj_count(mc_bus_dev->mc_io, +- 0, +- mc_bus_dev->mc_handle, +- &num_child_objects); +- if (error < 0) { +- dev_err(&mc_bus_dev->dev, "dprc_get_obj_count() failed: %d\n", +- error); +- return error; +- } +- +- if (num_child_objects != 0) { +- int i; +- +- child_obj_desc_array = +- devm_kmalloc_array(&mc_bus_dev->dev, num_child_objects, +- sizeof(*child_obj_desc_array), +- GFP_KERNEL); +- if (!child_obj_desc_array) +- return -ENOMEM; +- +- /* +- * Discover objects currently present in the physical DPRC: +- */ +- dprc_get_obj_failures = 0; +- for (i = 0; i < num_child_objects; i++) { +- struct dprc_obj_desc *obj_desc = +- &child_obj_desc_array[i]; +- +- error = dprc_get_obj(mc_bus_dev->mc_io, +- 0, +- mc_bus_dev->mc_handle, +- i, obj_desc); +- if (error < 0) { +- dev_err(&mc_bus_dev->dev, +- "dprc_get_obj(i=%d) failed: %d\n", +- i, error); +- /* +- * Mark the obj entry as "invalid", by using the +- * empty string as obj type: +- */ +- obj_desc->type[0] = '\0'; +- obj_desc->id = error; +- dprc_get_obj_failures++; +- continue; +- } +- +- /* +- * add a quirk for all versions of dpsec < 4.0...none +- * are coherent regardless of what the MC reports. +- */ +- if ((strcmp(obj_desc->type, "dpseci") == 0) && +- (obj_desc->ver_major < 4)) +- obj_desc->flags |= +- DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY; +- +- irq_count += obj_desc->irq_count; +- dev_dbg(&mc_bus_dev->dev, +- "Discovered object: type %s, id %d\n", +- obj_desc->type, obj_desc->id); +- } +- +- if (dprc_get_obj_failures != 0) { +- dev_err(&mc_bus_dev->dev, +- "%d out of %d devices could not be retrieved\n", +- dprc_get_obj_failures, num_child_objects); +- } +- } +- +- *total_irq_count = irq_count; +- dprc_remove_devices(mc_bus_dev, child_obj_desc_array, +- num_child_objects); +- +- dprc_add_new_devices(mc_bus_dev, child_obj_desc_array, +- num_child_objects); +- +- if (child_obj_desc_array) +- devm_kfree(&mc_bus_dev->dev, child_obj_desc_array); +- +- return 0; +-} +-EXPORT_SYMBOL_GPL(dprc_scan_objects); +- +-/** +- * dprc_scan_container - Scans a physical DPRC and synchronizes Linux bus state +- * +- * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object +- * +- * Scans the physical DPRC and synchronizes the state of the Linux +- * bus driver with the actual state of the MC by adding and removing +- * devices as appropriate. +- */ +-int dprc_scan_container(struct fsl_mc_device *mc_bus_dev) +-{ +- int error; +- unsigned int irq_count; +- struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); +- +- fsl_mc_init_all_resource_pools(mc_bus_dev); +- +- /* +- * Discover objects in the DPRC: +- */ +- mutex_lock(&mc_bus->scan_mutex); +- error = dprc_scan_objects(mc_bus_dev, &irq_count); +- mutex_unlock(&mc_bus->scan_mutex); +- if (error < 0) +- goto error; +- +- if (dev_get_msi_domain(&mc_bus_dev->dev) && !mc_bus->irq_resources) { +- if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) { +- dev_warn(&mc_bus_dev->dev, +- "IRQs needed (%u) exceed IRQs preallocated (%u)\n", +- irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); +- } +- +- error = fsl_mc_populate_irq_pool( +- mc_bus, +- FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); +- if (error < 0) +- goto error; +- } +- +- return 0; +-error: +- fsl_mc_cleanup_all_resource_pools(mc_bus_dev); +- return error; +-} +-EXPORT_SYMBOL_GPL(dprc_scan_container); +- +-/** +- * dprc_irq0_handler - Regular ISR for DPRC interrupt 0 +- * +- * @irq: IRQ number of the interrupt being handled +- * @arg: Pointer to device structure +- */ +-static irqreturn_t dprc_irq0_handler(int irq_num, void *arg) +-{ +- return IRQ_WAKE_THREAD; +-} +- +-/** +- * dprc_irq0_handler_thread - Handler thread function for DPRC interrupt 0 +- * +- * @irq: IRQ number of the interrupt being handled +- * @arg: Pointer to device structure +- */ +-static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg) +-{ +- int error; +- u32 status; +- struct device *dev = arg; +- struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); +- struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); +- struct fsl_mc_io *mc_io = mc_dev->mc_io; +- struct msi_desc *msi_desc = mc_dev->irqs[0]->msi_desc; +- +- dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n", +- irq_num, smp_processor_id()); +- +- if (WARN_ON(!(mc_dev->flags & FSL_MC_IS_DPRC))) +- return IRQ_HANDLED; +- +- mutex_lock(&mc_bus->scan_mutex); +- if (WARN_ON(!msi_desc || msi_desc->irq != (u32)irq_num)) +- goto out; +- +- status = 0; +- error = dprc_get_irq_status(mc_io, 0, mc_dev->mc_handle, 0, +- &status); +- if (error < 0) { +- dev_err(dev, +- "dprc_get_irq_status() failed: %d\n", error); +- goto out; +- } +- +- error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, +- status); +- if (error < 0) { +- dev_err(dev, +- "dprc_clear_irq_status() failed: %d\n", error); +- goto out; +- } +- +- if (status & (DPRC_IRQ_EVENT_OBJ_ADDED | +- DPRC_IRQ_EVENT_OBJ_REMOVED | +- DPRC_IRQ_EVENT_CONTAINER_DESTROYED | +- DPRC_IRQ_EVENT_OBJ_DESTROYED | +- DPRC_IRQ_EVENT_OBJ_CREATED)) { +- unsigned int irq_count; +- +- error = dprc_scan_objects(mc_dev, &irq_count); +- if (error < 0) { +- /* +- * If the error is -ENXIO, we ignore it, as it indicates +- * that the object scan was aborted, as we detected that +- * an object was removed from the DPRC in the MC, while +- * we were scanning the DPRC. +- */ +- if (error != -ENXIO) { +- dev_err(dev, "dprc_scan_objects() failed: %d\n", +- error); +- } +- +- goto out; +- } +- +- if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) { +- dev_warn(dev, +- "IRQs needed (%u) exceed IRQs preallocated (%u)\n", +- irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); +- } +- } +- +-out: +- mutex_unlock(&mc_bus->scan_mutex); +- return IRQ_HANDLED; +-} +- +-/* +- * Disable and clear interrupt for a given DPRC object +- */ +-static int disable_dprc_irq(struct fsl_mc_device *mc_dev) +-{ +- int error; +- struct fsl_mc_io *mc_io = mc_dev->mc_io; +- +- WARN_ON(mc_dev->obj_desc.irq_count != 1); +- +- /* +- * Disable generation of interrupt, while we configure it: +- */ +- error = dprc_set_irq_enable(mc_io, 0, mc_dev->mc_handle, 0, 0); +- if (error < 0) { +- dev_err(&mc_dev->dev, +- "Disabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n", +- error); +- return error; +- } +- +- /* +- * Disable all interrupt causes for the interrupt: +- */ +- error = dprc_set_irq_mask(mc_io, 0, mc_dev->mc_handle, 0, 0x0); +- if (error < 0) { +- dev_err(&mc_dev->dev, +- "Disabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n", +- error); +- return error; +- } +- +- /* +- * Clear any leftover interrupts: +- */ +- error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, ~0x0U); +- if (error < 0) { +- dev_err(&mc_dev->dev, +- "Disabling DPRC IRQ failed: dprc_clear_irq_status() failed: %d\n", +- error); +- return error; +- } +- +- return 0; +-} +- +-static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev) +-{ +- int error; +- struct fsl_mc_device_irq *irq = mc_dev->irqs[0]; +- +- WARN_ON(mc_dev->obj_desc.irq_count != 1); +- +- /* +- * NOTE: devm_request_threaded_irq() invokes the device-specific +- * function that programs the MSI physically in the device +- */ +- error = devm_request_threaded_irq(&mc_dev->dev, +- irq->msi_desc->irq, +- dprc_irq0_handler, +- dprc_irq0_handler_thread, +- IRQF_NO_SUSPEND | IRQF_ONESHOT, +- "FSL MC DPRC irq0", +- &mc_dev->dev); +- if (error < 0) { +- dev_err(&mc_dev->dev, +- "devm_request_threaded_irq() failed: %d\n", +- error); +- return error; +- } +- +- return 0; +-} +- +-static int enable_dprc_irq(struct fsl_mc_device *mc_dev) +-{ +- int error; +- +- /* +- * Enable all interrupt causes for the interrupt: +- */ +- error = dprc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, +- ~0x0u); +- if (error < 0) { +- dev_err(&mc_dev->dev, +- "Enabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n", +- error); +- +- return error; +- } +- +- /* +- * Enable generation of the interrupt: +- */ +- error = dprc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, 1); +- if (error < 0) { +- dev_err(&mc_dev->dev, +- "Enabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n", +- error); +- +- return error; +- } +- +- return 0; +-} +- +-/* +- * Setup interrupt for a given DPRC device +- */ +-static int dprc_setup_irq(struct fsl_mc_device *mc_dev) +-{ +- int error; +- +- error = fsl_mc_allocate_irqs(mc_dev); +- if (error < 0) +- return error; +- +- error = disable_dprc_irq(mc_dev); +- if (error < 0) +- goto error_free_irqs; +- +- error = register_dprc_irq_handler(mc_dev); +- if (error < 0) +- goto error_free_irqs; +- +- error = enable_dprc_irq(mc_dev); +- if (error < 0) +- goto error_free_irqs; +- +- return 0; +- +-error_free_irqs: +- fsl_mc_free_irqs(mc_dev); +- return error; +-} +- +-/** +- * dprc_probe - callback invoked when a DPRC is being bound to this driver +- * +- * @mc_dev: Pointer to fsl-mc device representing a DPRC +- * +- * It opens the physical DPRC in the MC. +- * It scans the DPRC to discover the MC objects contained in it. +- * It creates the interrupt pool for the MC bus associated with the DPRC. +- * It configures the interrupts for the DPRC device itself. +- */ +-static int dprc_probe(struct fsl_mc_device *mc_dev) +-{ +- int error; +- size_t region_size; +- struct device *parent_dev = mc_dev->dev.parent; +- struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); +- bool mc_io_created = false; +- bool msi_domain_set = false; +- +- if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0)) +- return -EINVAL; +- +- if (WARN_ON(dev_get_msi_domain(&mc_dev->dev))) +- return -EINVAL; +- +- if (!mc_dev->mc_io) { +- /* +- * This is a child DPRC: +- */ +- if (WARN_ON(!dev_is_fsl_mc(parent_dev))) +- return -EINVAL; +- +- if (WARN_ON(mc_dev->obj_desc.region_count == 0)) +- return -EINVAL; +- +- region_size = mc_dev->regions[0].end - +- mc_dev->regions[0].start + 1; +- +- error = fsl_create_mc_io(&mc_dev->dev, +- mc_dev->regions[0].start, +- region_size, +- NULL, +- FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, +- &mc_dev->mc_io); +- if (error < 0) +- return error; +- +- mc_io_created = true; +- +- /* +- * Inherit parent MSI domain: +- */ +- dev_set_msi_domain(&mc_dev->dev, +- dev_get_msi_domain(parent_dev)); +- msi_domain_set = true; +- } else { +- /* +- * This is a root DPRC +- */ +- struct irq_domain *mc_msi_domain; +- +- if (WARN_ON(dev_is_fsl_mc(parent_dev))) +- return -EINVAL; +- +- error = fsl_mc_find_msi_domain(parent_dev, +- &mc_msi_domain); +- if (error < 0) { +- dev_warn(&mc_dev->dev, +- "WARNING: MC bus without interrupt support\n"); +- } else { +- dev_set_msi_domain(&mc_dev->dev, mc_msi_domain); +- msi_domain_set = true; +- } +- } +- +- error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id, +- &mc_dev->mc_handle); +- if (error < 0) { +- dev_err(&mc_dev->dev, "dprc_open() failed: %d\n", error); +- goto error_cleanup_msi_domain; +- } +- +- error = dprc_get_attributes(mc_dev->mc_io, 0, mc_dev->mc_handle, +- &mc_bus->dprc_attr); +- if (error < 0) { +- dev_err(&mc_dev->dev, "dprc_get_attributes() failed: %d\n", +- error); +- goto error_cleanup_open; +- } +- +- if (mc_bus->dprc_attr.version.major < DPRC_MIN_VER_MAJOR || +- (mc_bus->dprc_attr.version.major == DPRC_MIN_VER_MAJOR && +- mc_bus->dprc_attr.version.minor < DPRC_MIN_VER_MINOR)) { +- dev_err(&mc_dev->dev, +- "ERROR: DPRC version %d.%d not supported\n", +- mc_bus->dprc_attr.version.major, +- mc_bus->dprc_attr.version.minor); +- error = -ENOTSUPP; +- goto error_cleanup_open; +- } +- +- mutex_init(&mc_bus->scan_mutex); +- +- /* +- * Discover MC objects in DPRC object: +- */ +- error = dprc_scan_container(mc_dev); +- if (error < 0) +- goto error_cleanup_open; +- +- /* +- * Configure interrupt for the DPRC object associated with this MC bus: +- */ +- error = dprc_setup_irq(mc_dev); +- if (error < 0) +- goto error_cleanup_open; +- +- dev_info(&mc_dev->dev, "DPRC device bound to driver"); +- return 0; +- +-error_cleanup_open: +- (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); +- +-error_cleanup_msi_domain: +- if (msi_domain_set) +- dev_set_msi_domain(&mc_dev->dev, NULL); +- +- if (mc_io_created) { +- fsl_destroy_mc_io(mc_dev->mc_io); +- mc_dev->mc_io = NULL; +- } +- +- return error; +-} +- +-/* +- * Tear down interrupt for a given DPRC object +- */ +-static void dprc_teardown_irq(struct fsl_mc_device *mc_dev) +-{ +- struct fsl_mc_device_irq *irq = mc_dev->irqs[0]; +- +- (void)disable_dprc_irq(mc_dev); +- +- devm_free_irq(&mc_dev->dev, irq->msi_desc->irq, &mc_dev->dev); +- +- fsl_mc_free_irqs(mc_dev); +-} +- +-/** +- * dprc_remove - callback invoked when a DPRC is being unbound from this driver +- * +- * @mc_dev: Pointer to fsl-mc device representing the DPRC +- * +- * It removes the DPRC's child objects from Linux (not from the MC) and +- * closes the DPRC device in the MC. +- * It tears down the interrupts that were configured for the DPRC device. +- * It destroys the interrupt pool associated with this MC bus. +- */ +-static int dprc_remove(struct fsl_mc_device *mc_dev) +-{ +- int error; +- struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); +- +- if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0)) +- return -EINVAL; +- if (WARN_ON(!mc_dev->mc_io)) +- return -EINVAL; +- +- if (WARN_ON(!mc_bus->irq_resources)) +- return -EINVAL; +- +- if (dev_get_msi_domain(&mc_dev->dev)) +- dprc_teardown_irq(mc_dev); +- +- device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove); +- +- if (dev_get_msi_domain(&mc_dev->dev)) { +- fsl_mc_cleanup_irq_pool(mc_bus); +- dev_set_msi_domain(&mc_dev->dev, NULL); +- } +- +- fsl_mc_cleanup_all_resource_pools(mc_dev); +- +- error = dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); +- if (error < 0) +- dev_err(&mc_dev->dev, "dprc_close() failed: %d\n", error); +- +- if (!fsl_mc_is_root_dprc(&mc_dev->dev)) { +- fsl_destroy_mc_io(mc_dev->mc_io); +- mc_dev->mc_io = NULL; +- } +- +- dev_info(&mc_dev->dev, "DPRC device unbound from driver"); +- return 0; +-} +- +-static const struct fsl_mc_device_id match_id_table[] = { +- { +- .vendor = FSL_MC_VENDOR_FREESCALE, +- .obj_type = "dprc"}, +- {.vendor = 0x0}, +-}; +- +-static struct fsl_mc_driver dprc_driver = { +- .driver = { +- .name = FSL_MC_DPRC_DRIVER_NAME, +- .owner = THIS_MODULE, +- .pm = NULL, +- }, +- .match_id_table = match_id_table, +- .probe = dprc_probe, +- .remove = dprc_remove, +-}; +- +-int __init dprc_driver_init(void) +-{ +- return fsl_mc_driver_register(&dprc_driver); +-} +- +-void dprc_driver_exit(void) +-{ +- fsl_mc_driver_unregister(&dprc_driver); +-} +--- /dev/null ++++ b/drivers/bus/fsl-mc/dprc-driver.c +@@ -0,0 +1,815 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Freescale data path resource container (DPRC) driver ++ * ++ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. ++ * Author: German Rivera <German.Rivera@freescale.com> ++ * ++ */ ++ ++#include <linux/module.h> ++#include <linux/slab.h> ++#include <linux/interrupt.h> ++#include <linux/msi.h> ++#include <linux/fsl/mc.h> ++ ++#include "fsl-mc-private.h" ++ ++#define FSL_MC_DPRC_DRIVER_NAME "fsl_mc_dprc" ++ ++struct fsl_mc_child_objs { ++ int child_count; ++ struct fsl_mc_obj_desc *child_array; ++}; ++ ++static bool fsl_mc_device_match(struct fsl_mc_device *mc_dev, ++ struct fsl_mc_obj_desc *obj_desc) ++{ ++ return mc_dev->obj_desc.id == obj_desc->id && ++ strcmp(mc_dev->obj_desc.type, obj_desc->type) == 0; ++ ++} ++ ++static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data) ++{ ++ int i; ++ struct fsl_mc_child_objs *objs; ++ struct fsl_mc_device *mc_dev; ++ ++ mc_dev = to_fsl_mc_device(dev); ++ objs = data; ++ ++ for (i = 0; i < objs->child_count; i++) { ++ struct fsl_mc_obj_desc *obj_desc = &objs->child_array[i]; ++ ++ if (strlen(obj_desc->type) != 0 && ++ fsl_mc_device_match(mc_dev, obj_desc)) ++ break; ++ } ++ ++ if (i == objs->child_count) ++ fsl_mc_device_remove(mc_dev); ++ ++ return 0; ++} ++ ++static int __fsl_mc_device_remove(struct device *dev, void *data) ++{ ++ fsl_mc_device_remove(to_fsl_mc_device(dev)); ++ return 0; ++} ++ ++/** ++ * dprc_remove_devices - Removes devices for objects removed from a DPRC ++ * ++ * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object ++ * @obj_desc_array: array of object descriptors for child objects currently ++ * present in the DPRC in the MC. ++ * @num_child_objects_in_mc: number of entries in obj_desc_array ++ * ++ * Synchronizes the state of the Linux bus driver with the actual state of ++ * the MC by removing devices that represent MC objects that have ++ * been dynamically removed in the physical DPRC. ++ */ ++static void dprc_remove_devices(struct fsl_mc_device *mc_bus_dev, ++ struct fsl_mc_obj_desc *obj_desc_array, ++ int num_child_objects_in_mc) ++{ ++ if (num_child_objects_in_mc != 0) { ++ /* ++ * Remove child objects that are in the DPRC in Linux, ++ * but not in the MC: ++ */ ++ struct fsl_mc_child_objs objs; ++ ++ objs.child_count = num_child_objects_in_mc; ++ objs.child_array = obj_desc_array; ++ device_for_each_child(&mc_bus_dev->dev, &objs, ++ __fsl_mc_device_remove_if_not_in_mc); ++ } else { ++ /* ++ * There are no child objects for this DPRC in the MC. ++ * So, remove all the child devices from Linux: ++ */ ++ device_for_each_child(&mc_bus_dev->dev, NULL, ++ __fsl_mc_device_remove); ++ } ++} ++ ++static int __fsl_mc_device_match(struct device *dev, void *data) ++{ ++ struct fsl_mc_obj_desc *obj_desc = data; ++ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); ++ ++ return fsl_mc_device_match(mc_dev, obj_desc); ++} ++ ++static struct fsl_mc_device *fsl_mc_device_lookup(struct fsl_mc_obj_desc ++ *obj_desc, ++ struct fsl_mc_device ++ *mc_bus_dev) ++{ ++ struct device *dev; ++ ++ dev = device_find_child(&mc_bus_dev->dev, obj_desc, ++ __fsl_mc_device_match); ++ ++ return dev ? to_fsl_mc_device(dev) : NULL; ++} ++ ++/** ++ * check_plugged_state_change - Check change in an MC object's plugged state ++ * ++ * @mc_dev: pointer to the fsl-mc device for a given MC object ++ * @obj_desc: pointer to the MC object's descriptor in the MC ++ * ++ * If the plugged state has changed from unplugged to plugged, the fsl-mc ++ * device is bound to the corresponding device driver. ++ * If the plugged state has changed from plugged to unplugged, the fsl-mc ++ * device is unbound from the corresponding device driver. ++ */ ++static void check_plugged_state_change(struct fsl_mc_device *mc_dev, ++ struct fsl_mc_obj_desc *obj_desc) ++{ ++ int error; ++ u32 plugged_flag_at_mc = ++ obj_desc->state & FSL_MC_OBJ_STATE_PLUGGED; ++ ++ if (plugged_flag_at_mc != ++ (mc_dev->obj_desc.state & FSL_MC_OBJ_STATE_PLUGGED)) { ++ if (plugged_flag_at_mc) { ++ mc_dev->obj_desc.state |= FSL_MC_OBJ_STATE_PLUGGED; ++ error = device_attach(&mc_dev->dev); ++ if (error < 0) { ++ dev_err(&mc_dev->dev, ++ "device_attach() failed: %d\n", ++ error); ++ } ++ } else { ++ mc_dev->obj_desc.state &= ~FSL_MC_OBJ_STATE_PLUGGED; ++ device_release_driver(&mc_dev->dev); ++ } ++ } ++} ++ ++/** ++ * dprc_add_new_devices - Adds devices to the logical bus for a DPRC ++ * ++ * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object ++ * @driver_override: driver override to apply to new objects found in the ++ * DPRC, or NULL, if none. ++ * @obj_desc_array: array of device descriptors for child devices currently ++ * present in the physical DPRC. ++ * @num_child_objects_in_mc: number of entries in obj_desc_array ++ * ++ * Synchronizes the state of the Linux bus driver with the actual ++ * state of the MC by adding objects that have been newly discovered ++ * in the physical DPRC. ++ */ ++static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev, ++ const char *driver_override, ++ struct fsl_mc_obj_desc *obj_desc_array, ++ int num_child_objects_in_mc) ++{ ++ int error; ++ int i; ++ ++ for (i = 0; i < num_child_objects_in_mc; i++) { ++ struct fsl_mc_device *child_dev; ++ struct fsl_mc_obj_desc *obj_desc = &obj_desc_array[i]; ++ ++ if (strlen(obj_desc->type) == 0) ++ continue; ++ ++ /* ++ * Check if device is already known to Linux: ++ */ ++ child_dev = fsl_mc_device_lookup(obj_desc, mc_bus_dev); ++ if (child_dev) { ++ check_plugged_state_change(child_dev, obj_desc); ++ put_device(&child_dev->dev); ++ continue; ++ } ++ ++ error = fsl_mc_device_add(obj_desc, NULL, &mc_bus_dev->dev, ++ driver_override, &child_dev); ++ if (error < 0) ++ continue; ++ } ++} ++ ++/** ++ * dprc_scan_objects - Discover objects in a DPRC ++ * ++ * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object ++ * @driver_override: driver override to apply to new objects found in the ++ * DPRC, or NULL, if none. ++ * @total_irq_count: If argument is provided the function populates the ++ * total number of IRQs created by objects in the DPRC. ++ * ++ * Detects objects added and removed from a DPRC and synchronizes the ++ * state of the Linux bus driver, MC by adding and removing ++ * devices accordingly. ++ * Two types of devices can be found in a DPRC: allocatable objects (e.g., ++ * dpbp, dpmcp) and non-allocatable devices (e.g., dprc, dpni). ++ * All allocatable devices needed to be probed before all non-allocatable ++ * devices, to ensure that device drivers for non-allocatable ++ * devices can allocate any type of allocatable devices. ++ * That is, we need to ensure that the corresponding resource pools are ++ * populated before they can get allocation requests from probe callbacks ++ * of the device drivers for the non-allocatable devices. ++ */ ++int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, ++ const char *driver_override, ++ unsigned int *total_irq_count) ++{ ++ int num_child_objects; ++ int dprc_get_obj_failures; ++ int error; ++ unsigned int irq_count = mc_bus_dev->obj_desc.irq_count; ++ struct fsl_mc_obj_desc *child_obj_desc_array = NULL; ++ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); ++ ++ error = dprc_get_obj_count(mc_bus_dev->mc_io, ++ 0, ++ mc_bus_dev->mc_handle, ++ &num_child_objects); ++ if (error < 0) { ++ dev_err(&mc_bus_dev->dev, "dprc_get_obj_count() failed: %d\n", ++ error); ++ return error; ++ } ++ ++ if (num_child_objects != 0) { ++ int i; ++ ++ child_obj_desc_array = ++ devm_kmalloc_array(&mc_bus_dev->dev, num_child_objects, ++ sizeof(*child_obj_desc_array), ++ GFP_KERNEL); ++ if (!child_obj_desc_array) ++ return -ENOMEM; ++ ++ /* ++ * Discover objects currently present in the physical DPRC: ++ */ ++ dprc_get_obj_failures = 0; ++ for (i = 0; i < num_child_objects; i++) { ++ struct fsl_mc_obj_desc *obj_desc = ++ &child_obj_desc_array[i]; ++ ++ error = dprc_get_obj(mc_bus_dev->mc_io, ++ 0, ++ mc_bus_dev->mc_handle, ++ i, obj_desc); ++ if (error < 0) { ++ dev_err(&mc_bus_dev->dev, ++ "dprc_get_obj(i=%d) failed: %d\n", ++ i, error); ++ /* ++ * Mark the obj entry as "invalid", by using the ++ * empty string as obj type: ++ */ ++ obj_desc->type[0] = '\0'; ++ obj_desc->id = error; ++ dprc_get_obj_failures++; ++ continue; ++ } ++ ++ /* ++ * add a quirk for all versions of dpsec < 4.0...none ++ * are coherent regardless of what the MC reports. ++ */ ++ if ((strcmp(obj_desc->type, "dpseci") == 0) && ++ (obj_desc->ver_major < 4)) ++ obj_desc->flags |= ++ FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY; ++ ++ irq_count += obj_desc->irq_count; ++ dev_dbg(&mc_bus_dev->dev, ++ "Discovered object: type %s, id %d\n", ++ obj_desc->type, obj_desc->id); ++ } ++ ++ if (dprc_get_obj_failures != 0) { ++ dev_err(&mc_bus_dev->dev, ++ "%d out of %d devices could not be retrieved\n", ++ dprc_get_obj_failures, num_child_objects); ++ } ++ } ++ ++ /* ++ * Allocate IRQ's before binding the scanned devices with their ++ * respective drivers. ++ */ ++ if (dev_get_msi_domain(&mc_bus_dev->dev) && !mc_bus->irq_resources) { ++ if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) { ++ dev_warn(&mc_bus_dev->dev, ++ "IRQs needed (%u) exceed IRQs preallocated (%u)\n", ++ irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); ++ } ++ ++ error = fsl_mc_populate_irq_pool(mc_bus, ++ FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); ++ if (error < 0) ++ return error; ++ } ++ ++ if (total_irq_count) ++ *total_irq_count = irq_count; ++ ++ dprc_remove_devices(mc_bus_dev, child_obj_desc_array, ++ num_child_objects); ++ ++ dprc_add_new_devices(mc_bus_dev, driver_override, child_obj_desc_array, ++ num_child_objects); ++ ++ if (child_obj_desc_array) ++ devm_kfree(&mc_bus_dev->dev, child_obj_desc_array); ++ ++ return 0; ++} ++ ++/** ++ * dprc_scan_container - Scans a physical DPRC and synchronizes Linux bus state ++ * ++ * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object ++ * ++ * Scans the physical DPRC and synchronizes the state of the Linux ++ * bus driver with the actual state of the MC by adding and removing ++ * devices as appropriate. ++ */ ++static int dprc_scan_container(struct fsl_mc_device *mc_bus_dev) ++{ ++ int error; ++ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); ++ ++ fsl_mc_init_all_resource_pools(mc_bus_dev); ++ ++ /* ++ * Discover objects in the DPRC: ++ */ ++ mutex_lock(&mc_bus->scan_mutex); ++ error = dprc_scan_objects(mc_bus_dev, NULL, NULL); ++ mutex_unlock(&mc_bus->scan_mutex); ++ if (error < 0) { ++ fsl_mc_cleanup_all_resource_pools(mc_bus_dev); ++ return error; ++ } ++ ++ return 0; ++} ++ ++/** ++ * dprc_irq0_handler - Regular ISR for DPRC interrupt 0 ++ * ++ * @irq: IRQ number of the interrupt being handled ++ * @arg: Pointer to device structure ++ */ ++static irqreturn_t dprc_irq0_handler(int irq_num, void *arg) ++{ ++ return IRQ_WAKE_THREAD; ++} ++ ++/** ++ * dprc_irq0_handler_thread - Handler thread function for DPRC interrupt 0 ++ * ++ * @irq: IRQ number of the interrupt being handled ++ * @arg: Pointer to device structure ++ */ ++static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg) ++{ ++ int error; ++ u32 status; ++ struct device *dev = arg; ++ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); ++ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); ++ struct fsl_mc_io *mc_io = mc_dev->mc_io; ++ struct msi_desc *msi_desc = mc_dev->irqs[0]->msi_desc; ++ ++ dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n", ++ irq_num, smp_processor_id()); ++ ++ if (!(mc_dev->flags & FSL_MC_IS_DPRC)) ++ return IRQ_HANDLED; ++ ++ mutex_lock(&mc_bus->scan_mutex); ++ if (!msi_desc || msi_desc->irq != (u32)irq_num) ++ goto out; ++ ++ status = 0; ++ error = dprc_get_irq_status(mc_io, 0, mc_dev->mc_handle, 0, ++ &status); ++ if (error < 0) { ++ dev_err(dev, ++ "dprc_get_irq_status() failed: %d\n", error); ++ goto out; ++ } ++ ++ error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, ++ status); ++ if (error < 0) { ++ dev_err(dev, ++ "dprc_clear_irq_status() failed: %d\n", error); ++ goto out; ++ } ++ ++ if (status & (DPRC_IRQ_EVENT_OBJ_ADDED | ++ DPRC_IRQ_EVENT_OBJ_REMOVED | ++ DPRC_IRQ_EVENT_CONTAINER_DESTROYED | ++ DPRC_IRQ_EVENT_OBJ_DESTROYED | ++ DPRC_IRQ_EVENT_OBJ_CREATED)) { ++ unsigned int irq_count; ++ ++ error = dprc_scan_objects(mc_dev, NULL, &irq_count); ++ if (error < 0) { ++ /* ++ * If the error is -ENXIO, we ignore it, as it indicates ++ * that the object scan was aborted, as we detected that ++ * an object was removed from the DPRC in the MC, while ++ * we were scanning the DPRC. ++ */ ++ if (error != -ENXIO) { ++ dev_err(dev, "dprc_scan_objects() failed: %d\n", ++ error); ++ } ++ ++ goto out; ++ } ++ ++ if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) { ++ dev_warn(dev, ++ "IRQs needed (%u) exceed IRQs preallocated (%u)\n", ++ irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); ++ } ++ } ++ ++out: ++ mutex_unlock(&mc_bus->scan_mutex); ++ return IRQ_HANDLED; ++} ++ ++/* ++ * Disable and clear interrupt for a given DPRC object ++ */ ++static int disable_dprc_irq(struct fsl_mc_device *mc_dev) ++{ ++ int error; ++ struct fsl_mc_io *mc_io = mc_dev->mc_io; ++ ++ /* ++ * Disable generation of interrupt, while we configure it: ++ */ ++ error = dprc_set_irq_enable(mc_io, 0, mc_dev->mc_handle, 0, 0); ++ if (error < 0) { ++ dev_err(&mc_dev->dev, ++ "Disabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n", ++ error); ++ return error; ++ } ++ ++ /* ++ * Disable all interrupt causes for the interrupt: ++ */ ++ error = dprc_set_irq_mask(mc_io, 0, mc_dev->mc_handle, 0, 0x0); ++ if (error < 0) { ++ dev_err(&mc_dev->dev, ++ "Disabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n", ++ error); ++ return error; ++ } ++ ++ /* ++ * Clear any leftover interrupts: ++ */ ++ error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, ~0x0U); ++ if (error < 0) { ++ dev_err(&mc_dev->dev, ++ "Disabling DPRC IRQ failed: dprc_clear_irq_status() failed: %d\n", ++ error); ++ return error; ++ } ++ ++ return 0; ++} ++ ++static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev) ++{ ++ int error; ++ struct fsl_mc_device_irq *irq = mc_dev->irqs[0]; ++ ++ /* ++ * NOTE: devm_request_threaded_irq() invokes the device-specific ++ * function that programs the MSI physically in the device ++ */ ++ error = devm_request_threaded_irq(&mc_dev->dev, ++ irq->msi_desc->irq, ++ dprc_irq0_handler, ++ dprc_irq0_handler_thread, ++ IRQF_NO_SUSPEND | IRQF_ONESHOT, ++ dev_name(&mc_dev->dev), ++ &mc_dev->dev); ++ if (error < 0) { ++ dev_err(&mc_dev->dev, ++ "devm_request_threaded_irq() failed: %d\n", ++ error); ++ return error; ++ } ++ ++ return 0; ++} ++ ++static int enable_dprc_irq(struct fsl_mc_device *mc_dev) ++{ ++ int error; ++ ++ /* ++ * Enable all interrupt causes for the interrupt: ++ */ ++ error = dprc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, ++ ~0x0u); ++ if (error < 0) { ++ dev_err(&mc_dev->dev, ++ "Enabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n", ++ error); ++ ++ return error; ++ } ++ ++ /* ++ * Enable generation of the interrupt: ++ */ ++ error = dprc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, 1); ++ if (error < 0) { ++ dev_err(&mc_dev->dev, ++ "Enabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n", ++ error); ++ ++ return error; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Setup interrupt for a given DPRC device ++ */ ++static int dprc_setup_irq(struct fsl_mc_device *mc_dev) ++{ ++ int error; ++ ++ error = fsl_mc_allocate_irqs(mc_dev); ++ if (error < 0) ++ return error; ++ ++ error = disable_dprc_irq(mc_dev); ++ if (error < 0) ++ goto error_free_irqs; ++ ++ error = register_dprc_irq_handler(mc_dev); ++ if (error < 0) ++ goto error_free_irqs; ++ ++ error = enable_dprc_irq(mc_dev); ++ if (error < 0) ++ goto error_free_irqs; ++ ++ return 0; ++ ++error_free_irqs: ++ fsl_mc_free_irqs(mc_dev); ++ return error; ++} ++ ++/** ++ * dprc_probe - callback invoked when a DPRC is being bound to this driver ++ * ++ * @mc_dev: Pointer to fsl-mc device representing a DPRC ++ * ++ * It opens the physical DPRC in the MC. ++ * It scans the DPRC to discover the MC objects contained in it. ++ * It creates the interrupt pool for the MC bus associated with the DPRC. ++ * It configures the interrupts for the DPRC device itself. ++ */ ++static int dprc_probe(struct fsl_mc_device *mc_dev) ++{ ++ int error; ++ size_t region_size; ++ struct device *parent_dev = mc_dev->dev.parent; ++ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); ++ bool mc_io_created = false; ++ bool msi_domain_set = false; ++ u16 major_ver, minor_ver; ++ ++ if (!is_fsl_mc_bus_dprc(mc_dev)) ++ return -EINVAL; ++ ++ if (dev_get_msi_domain(&mc_dev->dev)) ++ return -EINVAL; ++ ++ if (!mc_dev->mc_io) { ++ /* ++ * This is a child DPRC: ++ */ ++ if (!dev_is_fsl_mc(parent_dev)) ++ return -EINVAL; ++ ++ if (mc_dev->obj_desc.region_count == 0) ++ return -EINVAL; ++ ++ region_size = resource_size(mc_dev->regions); ++ ++ error = fsl_create_mc_io(&mc_dev->dev, ++ mc_dev->regions[0].start, ++ region_size, ++ NULL, ++ FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, ++ &mc_dev->mc_io); ++ if (error < 0) ++ return error; ++ ++ mc_io_created = true; ++ ++ /* ++ * Inherit parent MSI domain: ++ */ ++ dev_set_msi_domain(&mc_dev->dev, ++ dev_get_msi_domain(parent_dev)); ++ msi_domain_set = true; ++ } else { ++ /* ++ * This is a root DPRC ++ */ ++ struct irq_domain *mc_msi_domain; ++ ++ if (dev_is_fsl_mc(parent_dev)) ++ return -EINVAL; ++ ++ error = fsl_mc_find_msi_domain(parent_dev, ++ &mc_msi_domain); ++ if (error < 0) { ++ dev_warn(&mc_dev->dev, ++ "WARNING: MC bus without interrupt support\n"); ++ } else { ++ dev_set_msi_domain(&mc_dev->dev, mc_msi_domain); ++ msi_domain_set = true; ++ } ++ } ++ ++ error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id, ++ &mc_dev->mc_handle); ++ if (error < 0) { ++ dev_err(&mc_dev->dev, "dprc_open() failed: %d\n", error); ++ goto error_cleanup_msi_domain; ++ } ++ ++ error = dprc_get_attributes(mc_dev->mc_io, 0, mc_dev->mc_handle, ++ &mc_bus->dprc_attr); ++ if (error < 0) { ++ dev_err(&mc_dev->dev, "dprc_get_attributes() failed: %d\n", ++ error); ++ goto error_cleanup_open; ++ } ++ ++ error = dprc_get_api_version(mc_dev->mc_io, 0, ++ &major_ver, ++ &minor_ver); ++ if (error < 0) { ++ dev_err(&mc_dev->dev, "dprc_get_api_version() failed: %d\n", ++ error); ++ goto error_cleanup_open; ++ } ++ ++ if (major_ver < DPRC_MIN_VER_MAJOR || ++ (major_ver == DPRC_MIN_VER_MAJOR && ++ minor_ver < DPRC_MIN_VER_MINOR)) { ++ dev_err(&mc_dev->dev, ++ "ERROR: DPRC version %d.%d not supported\n", ++ major_ver, minor_ver); ++ error = -ENOTSUPP; ++ goto error_cleanup_open; ++ } ++ ++ mutex_init(&mc_bus->scan_mutex); ++ ++ /* ++ * Discover MC objects in DPRC object: ++ */ ++ error = dprc_scan_container(mc_dev); ++ if (error < 0) ++ goto error_cleanup_open; ++ ++ /* ++ * Configure interrupt for the DPRC object associated with this MC bus: ++ */ ++ error = dprc_setup_irq(mc_dev); ++ if (error < 0) ++ goto error_cleanup_open; ++ ++ dev_info(&mc_dev->dev, "DPRC device bound to driver"); ++ return 0; ++ ++error_cleanup_open: ++ (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); ++ ++error_cleanup_msi_domain: ++ if (msi_domain_set) ++ dev_set_msi_domain(&mc_dev->dev, NULL); ++ ++ if (mc_io_created) { ++ fsl_destroy_mc_io(mc_dev->mc_io); ++ mc_dev->mc_io = NULL; ++ } ++ ++ return error; ++} ++ ++/* ++ * Tear down interrupt for a given DPRC object ++ */ ++static void dprc_teardown_irq(struct fsl_mc_device *mc_dev) ++{ ++ struct fsl_mc_device_irq *irq = mc_dev->irqs[0]; ++ ++ (void)disable_dprc_irq(mc_dev); ++ ++ devm_free_irq(&mc_dev->dev, irq->msi_desc->irq, &mc_dev->dev); ++ ++ fsl_mc_free_irqs(mc_dev); ++} ++ ++/** ++ * dprc_remove - callback invoked when a DPRC is being unbound from this driver ++ * ++ * @mc_dev: Pointer to fsl-mc device representing the DPRC ++ * ++ * It removes the DPRC's child objects from Linux (not from the MC) and ++ * closes the DPRC device in the MC. ++ * It tears down the interrupts that were configured for the DPRC device. ++ * It destroys the interrupt pool associated with this MC bus. ++ */ ++static int dprc_remove(struct fsl_mc_device *mc_dev) ++{ ++ int error; ++ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); ++ ++ if (!is_fsl_mc_bus_dprc(mc_dev)) ++ return -EINVAL; ++ if (!mc_dev->mc_io) ++ return -EINVAL; ++ ++ if (!mc_bus->irq_resources) ++ return -EINVAL; ++ ++ if (dev_get_msi_domain(&mc_dev->dev)) ++ dprc_teardown_irq(mc_dev); ++ ++ device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove); ++ ++ if (dev_get_msi_domain(&mc_dev->dev)) { ++ fsl_mc_cleanup_irq_pool(mc_bus); ++ dev_set_msi_domain(&mc_dev->dev, NULL); ++ } ++ ++ fsl_mc_cleanup_all_resource_pools(mc_dev); ++ ++ error = dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); ++ if (error < 0) ++ dev_err(&mc_dev->dev, "dprc_close() failed: %d\n", error); ++ ++ if (!fsl_mc_is_root_dprc(&mc_dev->dev)) { ++ fsl_destroy_mc_io(mc_dev->mc_io); ++ mc_dev->mc_io = NULL; ++ } ++ ++ dev_info(&mc_dev->dev, "DPRC device unbound from driver"); ++ return 0; ++} ++ ++static const struct fsl_mc_device_id match_id_table[] = { ++ { ++ .vendor = FSL_MC_VENDOR_FREESCALE, ++ .obj_type = "dprc"}, ++ {.vendor = 0x0}, ++}; ++ ++static struct fsl_mc_driver dprc_driver = { ++ .driver = { ++ .name = FSL_MC_DPRC_DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .pm = NULL, ++ }, ++ .match_id_table = match_id_table, ++ .probe = dprc_probe, ++ .remove = dprc_remove, ++}; ++ ++int __init dprc_driver_init(void) ++{ ++ return fsl_mc_driver_register(&dprc_driver); ++} ++ ++void dprc_driver_exit(void) ++{ ++ fsl_mc_driver_unregister(&dprc_driver); ++} +--- /dev/null ++++ b/drivers/bus/fsl-mc/dprc.c +@@ -0,0 +1,575 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright 2013-2016 Freescale Semiconductor Inc. ++ * ++ */ ++#include <linux/kernel.h> ++#include <linux/fsl/mc.h> ++ ++#include "fsl-mc-private.h" ++ ++/** ++ * dprc_open() - Open DPRC object for use ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @container_id: Container ID to open ++ * @token: Returned token of DPRC object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ * ++ * @warning Required before any operation on the object. ++ */ ++int dprc_open(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ int container_id, ++ u16 *token) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ struct dprc_cmd_open *cmd_params; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, cmd_flags, ++ 0); ++ cmd_params = (struct dprc_cmd_open *)cmd.params; ++ cmd_params->container_id = cpu_to_le32(container_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = mc_cmd_hdr_read_token(&cmd); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(dprc_open); ++ ++/** ++ * dprc_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_close(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLOSE, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++EXPORT_SYMBOL_GPL(dprc_close); ++ ++/** ++ * dprc_reset_container - Reset child container. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @child_container_id: ID of the container to reset ++ * ++ * In case a software context crashes or becomes non-responsive, the parent ++ * may wish to reset its resources container before the software context is ++ * restarted. ++ * ++ * This routine informs all objects assigned to the child container that the ++ * container is being reset, so they may perform any cleanup operations that are ++ * needed. All objects handles that were owned by the child container shall be ++ * closed. ++ * ++ * Note that such request may be submitted even if the child software context ++ * has not crashed, but the resulting object cleanup operations will not be ++ * aware of that. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_reset_container(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ int child_container_id) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ struct dprc_cmd_reset_container *cmd_params; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_RESET_CONT, ++ cmd_flags, token); ++ cmd_params = (struct dprc_cmd_reset_container *)cmd.params; ++ cmd_params->child_container_id = cpu_to_le32(child_container_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++EXPORT_SYMBOL_GPL(dprc_reset_container); ++ ++/** ++ * dprc_set_irq() - Set IRQ information for the DPRC to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_set_irq(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ u8 irq_index, ++ struct dprc_irq_cfg *irq_cfg) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ struct dprc_cmd_set_irq *cmd_params; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ cmd_params = (struct dprc_cmd_set_irq *)cmd.params; ++ cmd_params->irq_val = cpu_to_le32(irq_cfg->val); ++ cmd_params->irq_index = irq_index; ++ cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr); ++ cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++/** ++ * dprc_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_set_irq_enable(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ u8 irq_index, ++ u8 en) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ struct dprc_cmd_set_irq_enable *cmd_params; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, token); ++ cmd_params = (struct dprc_cmd_set_irq_enable *)cmd.params; ++ cmd_params->enable = en & DPRC_ENABLE; ++ cmd_params->irq_index = irq_index; ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++/** ++ * dprc_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @irq_index: The interrupt index to configure ++ * @mask: event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting irq ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_set_irq_mask(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ u8 irq_index, ++ u32 mask) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ struct dprc_cmd_set_irq_mask *cmd_params; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_MASK, ++ cmd_flags, token); ++ cmd_params = (struct dprc_cmd_set_irq_mask *)cmd.params; ++ cmd_params->mask = cpu_to_le32(mask); ++ cmd_params->irq_index = irq_index; ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++/** ++ * dprc_get_irq_status() - Get the current status of any pending interrupts. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_irq_status(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ u8 irq_index, ++ u32 *status) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ struct dprc_cmd_get_irq_status *cmd_params; ++ struct dprc_rsp_get_irq_status *rsp_params; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_STATUS, ++ cmd_flags, token); ++ cmd_params = (struct dprc_cmd_get_irq_status *)cmd.params; ++ cmd_params->status = cpu_to_le32(*status); ++ cmd_params->irq_index = irq_index; ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ rsp_params = (struct dprc_rsp_get_irq_status *)cmd.params; ++ *status = le32_to_cpu(rsp_params->status); ++ ++ return 0; ++} ++ ++/** ++ * dprc_clear_irq_status() - Clear a pending interrupt's status ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @irq_index: The interrupt index to configure ++ * @status: bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_clear_irq_status(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ u8 irq_index, ++ u32 status) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ struct dprc_cmd_clear_irq_status *cmd_params; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, token); ++ cmd_params = (struct dprc_cmd_clear_irq_status *)cmd.params; ++ cmd_params->status = cpu_to_le32(status); ++ cmd_params->irq_index = irq_index; ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++/** ++ * dprc_get_attributes() - Obtains container attributes ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @attributes Returned container attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_attributes(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ struct dprc_attributes *attr) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ struct dprc_rsp_get_attributes *rsp_params; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ rsp_params = (struct dprc_rsp_get_attributes *)cmd.params; ++ attr->container_id = le32_to_cpu(rsp_params->container_id); ++ attr->icid = le32_to_cpu(rsp_params->icid); ++ attr->options = le32_to_cpu(rsp_params->options); ++ attr->portal_id = le32_to_cpu(rsp_params->portal_id); ++ ++ return 0; ++} ++ ++/** ++ * dprc_get_obj_count() - Obtains the number of objects in the DPRC ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @obj_count: Number of objects assigned to the DPRC ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_obj_count(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ int *obj_count) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ struct dprc_rsp_get_obj_count *rsp_params; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_COUNT, ++ cmd_flags, token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ rsp_params = (struct dprc_rsp_get_obj_count *)cmd.params; ++ *obj_count = le32_to_cpu(rsp_params->obj_count); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(dprc_get_obj_count); ++ ++/** ++ * dprc_get_obj() - Get general information on an object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @obj_index: Index of the object to be queried (< obj_count) ++ * @obj_desc: Returns the requested object descriptor ++ * ++ * The object descriptors are retrieved one by one by incrementing ++ * obj_index up to (not including) the value of obj_count returned ++ * from dprc_get_obj_count(). dprc_get_obj_count() must ++ * be called prior to dprc_get_obj(). ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_obj(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ int obj_index, ++ struct fsl_mc_obj_desc *obj_desc) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ struct dprc_cmd_get_obj *cmd_params; ++ struct dprc_rsp_get_obj *rsp_params; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ, ++ cmd_flags, ++ token); ++ cmd_params = (struct dprc_cmd_get_obj *)cmd.params; ++ cmd_params->obj_index = cpu_to_le32(obj_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ rsp_params = (struct dprc_rsp_get_obj *)cmd.params; ++ obj_desc->id = le32_to_cpu(rsp_params->id); ++ obj_desc->vendor = le16_to_cpu(rsp_params->vendor); ++ obj_desc->irq_count = rsp_params->irq_count; ++ obj_desc->region_count = rsp_params->region_count; ++ obj_desc->state = le32_to_cpu(rsp_params->state); ++ obj_desc->ver_major = le16_to_cpu(rsp_params->version_major); ++ obj_desc->ver_minor = le16_to_cpu(rsp_params->version_minor); ++ obj_desc->flags = le16_to_cpu(rsp_params->flags); ++ strncpy(obj_desc->type, rsp_params->type, 16); ++ obj_desc->type[15] = '\0'; ++ strncpy(obj_desc->label, rsp_params->label, 16); ++ obj_desc->label[15] = '\0'; ++ return 0; ++} ++EXPORT_SYMBOL_GPL(dprc_get_obj); ++ ++/** ++ * dprc_set_obj_irq() - Set IRQ information for object to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @obj_type: Type of the object to set its IRQ ++ * @obj_id: ID of the object to set its IRQ ++ * @irq_index: The interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_set_obj_irq(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ char *obj_type, ++ int obj_id, ++ u8 irq_index, ++ struct dprc_irq_cfg *irq_cfg) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ struct dprc_cmd_set_obj_irq *cmd_params; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_IRQ, ++ cmd_flags, ++ token); ++ cmd_params = (struct dprc_cmd_set_obj_irq *)cmd.params; ++ cmd_params->irq_val = cpu_to_le32(irq_cfg->val); ++ cmd_params->irq_index = irq_index; ++ cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr); ++ cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num); ++ cmd_params->obj_id = cpu_to_le32(obj_id); ++ strncpy(cmd_params->obj_type, obj_type, 16); ++ cmd_params->obj_type[15] = '\0'; ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++EXPORT_SYMBOL_GPL(dprc_set_obj_irq); ++ ++/** ++ * dprc_get_obj_region() - Get region information for a specified object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @obj_type; Object type as returned in dprc_get_obj() ++ * @obj_id: Unique object instance as returned in dprc_get_obj() ++ * @region_index: The specific region to query ++ * @region_desc: Returns the requested region descriptor ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_obj_region(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ char *obj_type, ++ int obj_id, ++ u8 region_index, ++ struct dprc_region_desc *region_desc) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ struct dprc_cmd_get_obj_region *cmd_params; ++ struct dprc_rsp_get_obj_region *rsp_params; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG, ++ cmd_flags, token); ++ cmd_params = (struct dprc_cmd_get_obj_region *)cmd.params; ++ cmd_params->obj_id = cpu_to_le32(obj_id); ++ cmd_params->region_index = region_index; ++ strncpy(cmd_params->obj_type, obj_type, 16); ++ cmd_params->obj_type[15] = '\0'; ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ rsp_params = (struct dprc_rsp_get_obj_region *)cmd.params; ++ region_desc->base_offset = le32_to_cpu(rsp_params->base_addr); ++ region_desc->size = le32_to_cpu(rsp_params->size); ++ region_desc->type = rsp_params->type; ++ region_desc->flags = le32_to_cpu(rsp_params->flags); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(dprc_get_obj_region); ++ ++/** ++ * dprc_get_api_version - Get Data Path Resource Container API version ++ * @mc_io: Pointer to Mc portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @major_ver: Major version of Data Path Resource Container API ++ * @minor_ver: Minor version of Data Path Resource Container API ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_api_version(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 *major_ver, ++ u16 *minor_ver) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_API_VERSION, ++ cmd_flags, 0); ++ ++ /* send command to mc */ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ mc_cmd_read_api_version(&cmd, major_ver, minor_ver); ++ ++ return 0; ++} ++ ++/** ++ * dprc_get_container_id - Get container ID associated with a given portal. ++ * @mc_io: Pointer to Mc portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @container_id: Requested container id ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_container_id(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ int *container_id) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONT_ID, ++ cmd_flags, ++ 0); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *container_id = (int)mc_cmd_read_object_id(&cmd); ++ ++ return 0; ++} +--- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c ++++ /dev/null +@@ -1,668 +0,0 @@ +-/* +- * Freescale MC object device allocator driver +- * +- * Copyright (C) 2013 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 <linux/module.h> +-#include <linux/msi.h> +-#include "../include/mc-bus.h" +-#include "../include/mc-sys.h" +-#include "../include/dpbp-cmd.h" +-#include "../include/dpcon-cmd.h" +- +-#include "fsl-mc-private.h" +- +-#define FSL_MC_IS_ALLOCATABLE(_obj_type) \ +- (strcmp(_obj_type, "dpbp") == 0 || \ +- strcmp(_obj_type, "dpmcp") == 0 || \ +- strcmp(_obj_type, "dpcon") == 0) +- +-/** +- * fsl_mc_resource_pool_add_device - add allocatable device to a resource +- * pool of a given MC bus +- * +- * @mc_bus: pointer to the MC bus +- * @pool_type: MC bus pool type +- * @mc_dev: Pointer to allocatable MC object device +- * +- * It adds an allocatable MC object device to a container's resource pool of +- * the given resource type +- */ +-static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus +- *mc_bus, +- enum fsl_mc_pool_type +- pool_type, +- struct fsl_mc_device +- *mc_dev) +-{ +- struct fsl_mc_resource_pool *res_pool; +- struct fsl_mc_resource *resource; +- struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; +- int error = -EINVAL; +- +- if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)) +- goto out; +- if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type))) +- goto out; +- if (WARN_ON(mc_dev->resource)) +- goto out; +- +- res_pool = &mc_bus->resource_pools[pool_type]; +- if (WARN_ON(res_pool->type != pool_type)) +- goto out; +- if (WARN_ON(res_pool->mc_bus != mc_bus)) +- goto out; +- +- mutex_lock(&res_pool->mutex); +- +- if (WARN_ON(res_pool->max_count < 0)) +- goto out_unlock; +- if (WARN_ON(res_pool->free_count < 0 || +- res_pool->free_count > res_pool->max_count)) +- goto out_unlock; +- +- resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource), +- GFP_KERNEL); +- if (!resource) { +- error = -ENOMEM; +- dev_err(&mc_bus_dev->dev, +- "Failed to allocate memory for fsl_mc_resource\n"); +- goto out_unlock; +- } +- +- resource->type = pool_type; +- resource->id = mc_dev->obj_desc.id; +- resource->data = mc_dev; +- resource->parent_pool = res_pool; +- INIT_LIST_HEAD(&resource->node); +- list_add_tail(&resource->node, &res_pool->free_list); +- mc_dev->resource = resource; +- res_pool->free_count++; +- res_pool->max_count++; +- error = 0; +-out_unlock: +- mutex_unlock(&res_pool->mutex); +-out: +- return error; +-} +- +-/** +- * fsl_mc_resource_pool_remove_device - remove an allocatable device from a +- * resource pool +- * +- * @mc_dev: Pointer to allocatable MC object device +- * +- * It permanently removes an allocatable MC object device from the resource +- * pool, the device is currently in, as long as it is in the pool's free list. +- */ +-static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device +- *mc_dev) +-{ +- struct fsl_mc_device *mc_bus_dev; +- struct fsl_mc_bus *mc_bus; +- struct fsl_mc_resource_pool *res_pool; +- struct fsl_mc_resource *resource; +- int error = -EINVAL; +- +- if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type))) +- goto out; +- +- resource = mc_dev->resource; +- if (WARN_ON(!resource || resource->data != mc_dev)) +- goto out; +- +- mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); +- mc_bus = to_fsl_mc_bus(mc_bus_dev); +- res_pool = resource->parent_pool; +- if (WARN_ON(res_pool != &mc_bus->resource_pools[resource->type])) +- goto out; +- +- mutex_lock(&res_pool->mutex); +- +- if (WARN_ON(res_pool->max_count <= 0)) +- goto out_unlock; +- if (WARN_ON(res_pool->free_count <= 0 || +- res_pool->free_count > res_pool->max_count)) +- goto out_unlock; +- +- /* +- * If the device is currently allocated, its resource is not +- * in the free list and thus, the device cannot be removed. +- */ +- if (list_empty(&resource->node)) { +- error = -EBUSY; +- dev_err(&mc_bus_dev->dev, +- "Device %s cannot be removed from resource pool\n", +- dev_name(&mc_dev->dev)); +- goto out_unlock; +- } +- +- list_del_init(&resource->node); +- res_pool->free_count--; +- res_pool->max_count--; +- +- devm_kfree(&mc_bus_dev->dev, resource); +- mc_dev->resource = NULL; +- error = 0; +-out_unlock: +- mutex_unlock(&res_pool->mutex); +-out: +- return error; +-} +- +-static const char *const fsl_mc_pool_type_strings[] = { +- [FSL_MC_POOL_DPMCP] = "dpmcp", +- [FSL_MC_POOL_DPBP] = "dpbp", +- [FSL_MC_POOL_DPCON] = "dpcon", +- [FSL_MC_POOL_IRQ] = "irq", +-}; +- +-static int __must_check object_type_to_pool_type(const char *object_type, +- enum fsl_mc_pool_type +- *pool_type) +-{ +- unsigned int i; +- +- for (i = 0; i < ARRAY_SIZE(fsl_mc_pool_type_strings); i++) { +- if (strcmp(object_type, fsl_mc_pool_type_strings[i]) == 0) { +- *pool_type = i; +- return 0; +- } +- } +- +- return -EINVAL; +-} +- +-int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, +- enum fsl_mc_pool_type pool_type, +- struct fsl_mc_resource **new_resource) +-{ +- struct fsl_mc_resource_pool *res_pool; +- struct fsl_mc_resource *resource; +- struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; +- int error = -EINVAL; +- +- BUILD_BUG_ON(ARRAY_SIZE(fsl_mc_pool_type_strings) != +- FSL_MC_NUM_POOL_TYPES); +- +- *new_resource = NULL; +- if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)) +- goto out; +- +- res_pool = &mc_bus->resource_pools[pool_type]; +- if (WARN_ON(res_pool->mc_bus != mc_bus)) +- goto out; +- +- mutex_lock(&res_pool->mutex); +- resource = list_first_entry_or_null(&res_pool->free_list, +- struct fsl_mc_resource, node); +- +- if (!resource) { +- WARN_ON(res_pool->free_count != 0); +- error = -ENXIO; +- dev_err(&mc_bus_dev->dev, +- "No more resources of type %s left\n", +- fsl_mc_pool_type_strings[pool_type]); +- goto out_unlock; +- } +- +- if (WARN_ON(resource->type != pool_type)) +- goto out_unlock; +- if (WARN_ON(resource->parent_pool != res_pool)) +- goto out_unlock; +- if (WARN_ON(res_pool->free_count <= 0 || +- res_pool->free_count > res_pool->max_count)) +- goto out_unlock; +- +- list_del_init(&resource->node); +- +- res_pool->free_count--; +- error = 0; +-out_unlock: +- mutex_unlock(&res_pool->mutex); +- *new_resource = resource; +-out: +- return error; +-} +-EXPORT_SYMBOL_GPL(fsl_mc_resource_allocate); +- +-void fsl_mc_resource_free(struct fsl_mc_resource *resource) +-{ +- struct fsl_mc_resource_pool *res_pool; +- +- res_pool = resource->parent_pool; +- if (WARN_ON(resource->type != res_pool->type)) +- return; +- +- mutex_lock(&res_pool->mutex); +- if (WARN_ON(res_pool->free_count < 0 || +- res_pool->free_count >= res_pool->max_count)) +- goto out_unlock; +- +- if (WARN_ON(!list_empty(&resource->node))) +- goto out_unlock; +- +- list_add_tail(&resource->node, &res_pool->free_list); +- res_pool->free_count++; +-out_unlock: +- mutex_unlock(&res_pool->mutex); +-} +-EXPORT_SYMBOL_GPL(fsl_mc_resource_free); +- +-/** +- * fsl_mc_object_allocate - Allocates a MC object device of the given +- * pool type from a given MC bus +- * +- * @mc_dev: MC device for which the MC object device is to be allocated +- * @pool_type: MC bus resource pool type +- * @new_mc_dev: Pointer to area where the pointer to the allocated +- * MC object device is to be returned +- * +- * This function allocates a MC object device from the device's parent DPRC, +- * from the corresponding MC bus' pool of allocatable MC object devices of +- * the given resource type. mc_dev cannot be a DPRC itself. +- * +- * NOTE: pool_type must be different from FSL_MC_POOL_MCP, since MC +- * portals are allocated using fsl_mc_portal_allocate(), instead of +- * this function. +- */ +-int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev, +- enum fsl_mc_pool_type pool_type, +- struct fsl_mc_device **new_mc_adev) +-{ +- struct fsl_mc_device *mc_bus_dev; +- struct fsl_mc_bus *mc_bus; +- struct fsl_mc_device *mc_adev; +- int error = -EINVAL; +- struct fsl_mc_resource *resource = NULL; +- +- *new_mc_adev = NULL; +- if (WARN_ON(mc_dev->flags & FSL_MC_IS_DPRC)) +- goto error; +- +- if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent))) +- goto error; +- +- if (WARN_ON(pool_type == FSL_MC_POOL_DPMCP)) +- goto error; +- +- mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); +- mc_bus = to_fsl_mc_bus(mc_bus_dev); +- error = fsl_mc_resource_allocate(mc_bus, pool_type, &resource); +- if (error < 0) +- goto error; +- +- mc_adev = resource->data; +- if (WARN_ON(!mc_adev)) +- goto error; +- +- *new_mc_adev = mc_adev; +- return 0; +-error: +- if (resource) +- fsl_mc_resource_free(resource); +- +- return error; +-} +-EXPORT_SYMBOL_GPL(fsl_mc_object_allocate); +- +-/** +- * fsl_mc_object_free - Returns an allocatable MC object device to the +- * corresponding resource pool of a given MC bus. +- * +- * @mc_adev: Pointer to the MC object device +- */ +-void fsl_mc_object_free(struct fsl_mc_device *mc_adev) +-{ +- struct fsl_mc_resource *resource; +- +- resource = mc_adev->resource; +- if (WARN_ON(resource->type == FSL_MC_POOL_DPMCP)) +- return; +- if (WARN_ON(resource->data != mc_adev)) +- return; +- +- fsl_mc_resource_free(resource); +-} +-EXPORT_SYMBOL_GPL(fsl_mc_object_free); +- +-/* +- * Initialize the interrupt pool associated with a MC bus. +- * It allocates a block of IRQs from the GIC-ITS +- */ +-int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, +- unsigned int irq_count) +-{ +- unsigned int i; +- struct msi_desc *msi_desc; +- struct fsl_mc_device_irq *irq_resources; +- struct fsl_mc_device_irq *mc_dev_irq; +- int error; +- struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; +- struct fsl_mc_resource_pool *res_pool = +- &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; +- +- if (WARN_ON(irq_count == 0 || +- irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS)) +- return -EINVAL; +- +- error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count); +- if (error < 0) +- return error; +- +- irq_resources = devm_kzalloc(&mc_bus_dev->dev, +- sizeof(*irq_resources) * irq_count, +- GFP_KERNEL); +- if (!irq_resources) { +- error = -ENOMEM; +- goto cleanup_msi_irqs; +- } +- +- for (i = 0; i < irq_count; i++) { +- mc_dev_irq = &irq_resources[i]; +- +- /* +- * NOTE: This mc_dev_irq's MSI addr/value pair will be set +- * by the fsl_mc_msi_write_msg() callback +- */ +- mc_dev_irq->resource.type = res_pool->type; +- mc_dev_irq->resource.data = mc_dev_irq; +- mc_dev_irq->resource.parent_pool = res_pool; +- INIT_LIST_HEAD(&mc_dev_irq->resource.node); +- list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list); +- } +- +- for_each_msi_entry(msi_desc, &mc_bus_dev->dev) { +- mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index]; +- mc_dev_irq->msi_desc = msi_desc; +- mc_dev_irq->resource.id = msi_desc->irq; +- } +- +- res_pool->max_count = irq_count; +- res_pool->free_count = irq_count; +- mc_bus->irq_resources = irq_resources; +- return 0; +- +-cleanup_msi_irqs: +- fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); +- return error; +-} +-EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool); +- +-/** +- * Teardown the interrupt pool associated with an MC bus. +- * It frees the IRQs that were allocated to the pool, back to the GIC-ITS. +- */ +-void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus) +-{ +- struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; +- struct fsl_mc_resource_pool *res_pool = +- &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; +- +- if (WARN_ON(!mc_bus->irq_resources)) +- return; +- +- if (WARN_ON(res_pool->max_count == 0)) +- return; +- +- if (WARN_ON(res_pool->free_count != res_pool->max_count)) +- return; +- +- INIT_LIST_HEAD(&res_pool->free_list); +- res_pool->max_count = 0; +- res_pool->free_count = 0; +- mc_bus->irq_resources = NULL; +- fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); +-} +-EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool); +- +-/** +- * It allocates the IRQs required by a given MC object device. The +- * IRQs are allocated from the interrupt pool associated with the +- * MC bus that contains the device, if the device is not a DPRC device. +- * Otherwise, the IRQs are allocated from the interrupt pool associated +- * with the MC bus that represents the DPRC device itself. +- */ +-int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev) +-{ +- int i; +- int irq_count; +- int res_allocated_count = 0; +- int error = -EINVAL; +- struct fsl_mc_device_irq **irqs = NULL; +- struct fsl_mc_bus *mc_bus; +- struct fsl_mc_resource_pool *res_pool; +- +- if (WARN_ON(mc_dev->irqs)) +- return -EINVAL; +- +- irq_count = mc_dev->obj_desc.irq_count; +- if (WARN_ON(irq_count == 0)) +- return -EINVAL; +- +- if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) +- mc_bus = to_fsl_mc_bus(mc_dev); +- else +- mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); +- +- if (WARN_ON(!mc_bus->irq_resources)) +- return -EINVAL; +- +- res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; +- if (res_pool->free_count < irq_count) { +- dev_err(&mc_dev->dev, +- "Not able to allocate %u irqs for device\n", irq_count); +- return -ENOSPC; +- } +- +- irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]), +- GFP_KERNEL); +- if (!irqs) +- return -ENOMEM; +- +- for (i = 0; i < irq_count; i++) { +- struct fsl_mc_resource *resource; +- +- error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ, +- &resource); +- if (error < 0) +- goto error_resource_alloc; +- +- irqs[i] = to_fsl_mc_irq(resource); +- res_allocated_count++; +- +- WARN_ON(irqs[i]->mc_dev); +- irqs[i]->mc_dev = mc_dev; +- irqs[i]->dev_irq_index = i; +- } +- +- mc_dev->irqs = irqs; +- return 0; +- +-error_resource_alloc: +- for (i = 0; i < res_allocated_count; i++) { +- irqs[i]->mc_dev = NULL; +- fsl_mc_resource_free(&irqs[i]->resource); +- } +- +- return error; +-} +-EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs); +- +-/* +- * It frees the IRQs that were allocated for a MC object device, by +- * returning them to the corresponding interrupt pool. +- */ +-void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev) +-{ +- int i; +- int irq_count; +- struct fsl_mc_bus *mc_bus; +- struct fsl_mc_device_irq **irqs = mc_dev->irqs; +- +- if (WARN_ON(!irqs)) +- return; +- +- irq_count = mc_dev->obj_desc.irq_count; +- +- if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) +- mc_bus = to_fsl_mc_bus(mc_dev); +- else +- mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); +- +- if (WARN_ON(!mc_bus->irq_resources)) +- return; +- +- for (i = 0; i < irq_count; i++) { +- WARN_ON(!irqs[i]->mc_dev); +- irqs[i]->mc_dev = NULL; +- fsl_mc_resource_free(&irqs[i]->resource); +- } +- +- mc_dev->irqs = NULL; +-} +-EXPORT_SYMBOL_GPL(fsl_mc_free_irqs); +- +-void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev) +-{ +- int pool_type; +- struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); +- +- for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) { +- struct fsl_mc_resource_pool *res_pool = +- &mc_bus->resource_pools[pool_type]; +- +- res_pool->type = pool_type; +- res_pool->max_count = 0; +- res_pool->free_count = 0; +- res_pool->mc_bus = mc_bus; +- INIT_LIST_HEAD(&res_pool->free_list); +- mutex_init(&res_pool->mutex); +- } +-} +- +-static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev, +- enum fsl_mc_pool_type pool_type) +-{ +- struct fsl_mc_resource *resource; +- struct fsl_mc_resource *next; +- struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); +- struct fsl_mc_resource_pool *res_pool = +- &mc_bus->resource_pools[pool_type]; +- int free_count = 0; +- +- WARN_ON(res_pool->type != pool_type); +- WARN_ON(res_pool->free_count != res_pool->max_count); +- +- list_for_each_entry_safe(resource, next, &res_pool->free_list, node) { +- free_count++; +- WARN_ON(resource->type != res_pool->type); +- WARN_ON(resource->parent_pool != res_pool); +- devm_kfree(&mc_bus_dev->dev, resource); +- } +- +- WARN_ON(free_count != res_pool->free_count); +-} +- +-void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev) +-{ +- int pool_type; +- +- for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) +- fsl_mc_cleanup_resource_pool(mc_bus_dev, pool_type); +-} +- +-/** +- * fsl_mc_allocator_probe - callback invoked when an allocatable device is +- * being added to the system +- */ +-static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev) +-{ +- enum fsl_mc_pool_type pool_type; +- struct fsl_mc_device *mc_bus_dev; +- struct fsl_mc_bus *mc_bus; +- int error; +- +- if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type))) +- return -EINVAL; +- +- mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); +- if (WARN_ON(!dev_is_fsl_mc(&mc_bus_dev->dev))) +- return -EINVAL; +- +- mc_bus = to_fsl_mc_bus(mc_bus_dev); +- error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type); +- if (error < 0) +- return error; +- +- error = fsl_mc_resource_pool_add_device(mc_bus, pool_type, mc_dev); +- if (error < 0) +- return error; +- +- dev_dbg(&mc_dev->dev, +- "Allocatable MC object device bound to fsl_mc_allocator driver"); +- return 0; +-} +- +-/** +- * fsl_mc_allocator_remove - callback invoked when an allocatable device is +- * being removed from the system +- */ +-static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev) +-{ +- int error; +- +- if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type))) +- return -EINVAL; +- +- if (mc_dev->resource) { +- error = fsl_mc_resource_pool_remove_device(mc_dev); +- if (error < 0) +- return error; +- } +- +- dev_dbg(&mc_dev->dev, +- "Allocatable MC object device unbound from fsl_mc_allocator driver"); +- return 0; +-} +- +-static const struct fsl_mc_device_id match_id_table[] = { +- { +- .vendor = FSL_MC_VENDOR_FREESCALE, +- .obj_type = "dpbp", +- }, +- { +- .vendor = FSL_MC_VENDOR_FREESCALE, +- .obj_type = "dpmcp", +- }, +- { +- .vendor = FSL_MC_VENDOR_FREESCALE, +- .obj_type = "dpcon", +- }, +- {.vendor = 0x0}, +-}; +- +-static struct fsl_mc_driver fsl_mc_allocator_driver = { +- .driver = { +- .name = "fsl_mc_allocator", +- .pm = NULL, +- }, +- .match_id_table = match_id_table, +- .probe = fsl_mc_allocator_probe, +- .remove = fsl_mc_allocator_remove, +-}; +- +-int __init fsl_mc_allocator_driver_init(void) +-{ +- return fsl_mc_driver_register(&fsl_mc_allocator_driver); +-} +- +-void fsl_mc_allocator_driver_exit(void) +-{ +- fsl_mc_driver_unregister(&fsl_mc_allocator_driver); +-} +--- /dev/null ++++ b/drivers/bus/fsl-mc/fsl-mc-allocator.c +@@ -0,0 +1,655 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * fsl-mc object allocator driver ++ * ++ * Copyright (C) 2013-2016 Freescale Semiconductor, Inc. ++ * ++ */ ++ ++#include <linux/module.h> ++#include <linux/msi.h> ++#include <linux/fsl/mc.h> ++ ++#include "fsl-mc-private.h" ++ ++static bool __must_check fsl_mc_is_allocatable(struct fsl_mc_device *mc_dev) ++{ ++ return is_fsl_mc_bus_dpbp(mc_dev) || ++ is_fsl_mc_bus_dpmcp(mc_dev) || ++ is_fsl_mc_bus_dpcon(mc_dev); ++} ++ ++/** ++ * fsl_mc_resource_pool_add_device - add allocatable object to a resource ++ * pool of a given fsl-mc bus ++ * ++ * @mc_bus: pointer to the fsl-mc bus ++ * @pool_type: pool type ++ * @mc_dev: pointer to allocatable fsl-mc device ++ */ ++static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus ++ *mc_bus, ++ enum fsl_mc_pool_type ++ pool_type, ++ struct fsl_mc_device ++ *mc_dev) ++{ ++ struct fsl_mc_resource_pool *res_pool; ++ struct fsl_mc_resource *resource; ++ struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; ++ int error = -EINVAL; ++ ++ if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES) ++ goto out; ++ if (!fsl_mc_is_allocatable(mc_dev)) ++ goto out; ++ if (mc_dev->resource) ++ goto out; ++ ++ res_pool = &mc_bus->resource_pools[pool_type]; ++ if (res_pool->type != pool_type) ++ goto out; ++ if (res_pool->mc_bus != mc_bus) ++ goto out; ++ ++ mutex_lock(&res_pool->mutex); ++ ++ if (res_pool->max_count < 0) ++ goto out_unlock; ++ if (res_pool->free_count < 0 || ++ res_pool->free_count > res_pool->max_count) ++ goto out_unlock; ++ ++ resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource), ++ GFP_KERNEL); ++ if (!resource) { ++ error = -ENOMEM; ++ dev_err(&mc_bus_dev->dev, ++ "Failed to allocate memory for fsl_mc_resource\n"); ++ goto out_unlock; ++ } ++ ++ resource->type = pool_type; ++ resource->id = mc_dev->obj_desc.id; ++ resource->data = mc_dev; ++ resource->parent_pool = res_pool; ++ INIT_LIST_HEAD(&resource->node); ++ list_add_tail(&resource->node, &res_pool->free_list); ++ mc_dev->resource = resource; ++ res_pool->free_count++; ++ res_pool->max_count++; ++ error = 0; ++out_unlock: ++ mutex_unlock(&res_pool->mutex); ++out: ++ return error; ++} ++ ++/** ++ * fsl_mc_resource_pool_remove_device - remove an allocatable device from a ++ * resource pool ++ * ++ * @mc_dev: pointer to allocatable fsl-mc device ++ * ++ * It permanently removes an allocatable fsl-mc device from the resource ++ * pool. It's an error if the device is in use. ++ */ ++static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device ++ *mc_dev) ++{ ++ struct fsl_mc_device *mc_bus_dev; ++ struct fsl_mc_bus *mc_bus; ++ struct fsl_mc_resource_pool *res_pool; ++ struct fsl_mc_resource *resource; ++ int error = -EINVAL; ++ ++ if (!fsl_mc_is_allocatable(mc_dev)) ++ goto out; ++ ++ resource = mc_dev->resource; ++ if (!resource || resource->data != mc_dev) ++ goto out; ++ ++ mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); ++ mc_bus = to_fsl_mc_bus(mc_bus_dev); ++ res_pool = resource->parent_pool; ++ if (res_pool != &mc_bus->resource_pools[resource->type]) ++ goto out; ++ ++ mutex_lock(&res_pool->mutex); ++ ++ if (res_pool->max_count <= 0) ++ goto out_unlock; ++ if (res_pool->free_count <= 0 || ++ res_pool->free_count > res_pool->max_count) ++ goto out_unlock; ++ ++ /* ++ * If the device is currently allocated, its resource is not ++ * in the free list and thus, the device cannot be removed. ++ */ ++ if (list_empty(&resource->node)) { ++ error = -EBUSY; ++ dev_err(&mc_bus_dev->dev, ++ "Device %s cannot be removed from resource pool\n", ++ dev_name(&mc_dev->dev)); ++ goto out_unlock; ++ } ++ ++ list_del_init(&resource->node); ++ res_pool->free_count--; ++ res_pool->max_count--; ++ ++ devm_kfree(&mc_bus_dev->dev, resource); ++ mc_dev->resource = NULL; ++ error = 0; ++out_unlock: ++ mutex_unlock(&res_pool->mutex); ++out: ++ return error; ++} ++ ++static const char *const fsl_mc_pool_type_strings[] = { ++ [FSL_MC_POOL_DPMCP] = "dpmcp", ++ [FSL_MC_POOL_DPBP] = "dpbp", ++ [FSL_MC_POOL_DPCON] = "dpcon", ++ [FSL_MC_POOL_IRQ] = "irq", ++}; ++ ++static int __must_check object_type_to_pool_type(const char *object_type, ++ enum fsl_mc_pool_type ++ *pool_type) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(fsl_mc_pool_type_strings); i++) { ++ if (strcmp(object_type, fsl_mc_pool_type_strings[i]) == 0) { ++ *pool_type = i; ++ return 0; ++ } ++ } ++ ++ return -EINVAL; ++} ++ ++int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, ++ enum fsl_mc_pool_type pool_type, ++ struct fsl_mc_resource **new_resource) ++{ ++ struct fsl_mc_resource_pool *res_pool; ++ struct fsl_mc_resource *resource; ++ struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; ++ int error = -EINVAL; ++ ++ BUILD_BUG_ON(ARRAY_SIZE(fsl_mc_pool_type_strings) != ++ FSL_MC_NUM_POOL_TYPES); ++ ++ *new_resource = NULL; ++ if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES) ++ goto out; ++ ++ res_pool = &mc_bus->resource_pools[pool_type]; ++ if (res_pool->mc_bus != mc_bus) ++ goto out; ++ ++ mutex_lock(&res_pool->mutex); ++ resource = list_first_entry_or_null(&res_pool->free_list, ++ struct fsl_mc_resource, node); ++ ++ if (!resource) { ++ error = -ENXIO; ++ dev_err(&mc_bus_dev->dev, ++ "No more resources of type %s left\n", ++ fsl_mc_pool_type_strings[pool_type]); ++ goto out_unlock; ++ } ++ ++ if (resource->type != pool_type) ++ goto out_unlock; ++ if (resource->parent_pool != res_pool) ++ goto out_unlock; ++ if (res_pool->free_count <= 0 || ++ res_pool->free_count > res_pool->max_count) ++ goto out_unlock; ++ ++ list_del_init(&resource->node); ++ ++ res_pool->free_count--; ++ error = 0; ++out_unlock: ++ mutex_unlock(&res_pool->mutex); ++ *new_resource = resource; ++out: ++ return error; ++} ++EXPORT_SYMBOL_GPL(fsl_mc_resource_allocate); ++ ++void fsl_mc_resource_free(struct fsl_mc_resource *resource) ++{ ++ struct fsl_mc_resource_pool *res_pool; ++ ++ res_pool = resource->parent_pool; ++ if (resource->type != res_pool->type) ++ return; ++ ++ mutex_lock(&res_pool->mutex); ++ if (res_pool->free_count < 0 || ++ res_pool->free_count >= res_pool->max_count) ++ goto out_unlock; ++ ++ if (!list_empty(&resource->node)) ++ goto out_unlock; ++ ++ list_add_tail(&resource->node, &res_pool->free_list); ++ res_pool->free_count++; ++out_unlock: ++ mutex_unlock(&res_pool->mutex); ++} ++EXPORT_SYMBOL_GPL(fsl_mc_resource_free); ++ ++/** ++ * fsl_mc_object_allocate - Allocates an fsl-mc object of the given ++ * pool type from a given fsl-mc bus instance ++ * ++ * @mc_dev: fsl-mc device which is used in conjunction with the ++ * allocated object ++ * @pool_type: pool type ++ * @new_mc_dev: pointer to area where the pointer to the allocated device ++ * is to be returned ++ * ++ * Allocatable objects are always used in conjunction with some functional ++ * device. This function allocates an object of the specified type from ++ * the DPRC containing the functional device. ++ * ++ * NOTE: pool_type must be different from FSL_MC_POOL_MCP, since MC ++ * portals are allocated using fsl_mc_portal_allocate(), instead of ++ * this function. ++ */ ++int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev, ++ enum fsl_mc_pool_type pool_type, ++ struct fsl_mc_device **new_mc_adev) ++{ ++ struct fsl_mc_device *mc_bus_dev; ++ struct fsl_mc_bus *mc_bus; ++ struct fsl_mc_device *mc_adev; ++ int error = -EINVAL; ++ struct fsl_mc_resource *resource = NULL; ++ ++ *new_mc_adev = NULL; ++ if (mc_dev->flags & FSL_MC_IS_DPRC) ++ goto error; ++ ++ if (!dev_is_fsl_mc(mc_dev->dev.parent)) ++ goto error; ++ ++ if (pool_type == FSL_MC_POOL_DPMCP) ++ goto error; ++ ++ mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); ++ mc_bus = to_fsl_mc_bus(mc_bus_dev); ++ error = fsl_mc_resource_allocate(mc_bus, pool_type, &resource); ++ if (error < 0) ++ goto error; ++ ++ mc_adev = resource->data; ++ if (!mc_adev) ++ goto error; ++ ++ *new_mc_adev = mc_adev; ++ return 0; ++error: ++ if (resource) ++ fsl_mc_resource_free(resource); ++ ++ return error; ++} ++EXPORT_SYMBOL_GPL(fsl_mc_object_allocate); ++ ++/** ++ * fsl_mc_object_free - Returns an fsl-mc object to the resource ++ * pool where it came from. ++ * @mc_adev: Pointer to the fsl-mc device ++ */ ++void fsl_mc_object_free(struct fsl_mc_device *mc_adev) ++{ ++ struct fsl_mc_resource *resource; ++ ++ resource = mc_adev->resource; ++ if (resource->type == FSL_MC_POOL_DPMCP) ++ return; ++ if (resource->data != mc_adev) ++ return; ++ ++ fsl_mc_resource_free(resource); ++} ++EXPORT_SYMBOL_GPL(fsl_mc_object_free); ++ ++/* ++ * A DPRC and the devices in the DPRC all share the same GIC-ITS device ++ * ID. A block of IRQs is pre-allocated and maintained in a pool ++ * from which devices can allocate them when needed. ++ */ ++ ++/* ++ * Initialize the interrupt pool associated with an fsl-mc bus. ++ * It allocates a block of IRQs from the GIC-ITS. ++ */ ++int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, ++ unsigned int irq_count) ++{ ++ unsigned int i; ++ struct msi_desc *msi_desc; ++ struct fsl_mc_device_irq *irq_resources; ++ struct fsl_mc_device_irq *mc_dev_irq; ++ int error; ++ struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; ++ struct fsl_mc_resource_pool *res_pool = ++ &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; ++ ++ if (irq_count == 0 || ++ irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) ++ return -EINVAL; ++ ++ error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count); ++ if (error < 0) ++ return error; ++ ++ irq_resources = devm_kzalloc(&mc_bus_dev->dev, ++ sizeof(*irq_resources) * irq_count, ++ GFP_KERNEL); ++ if (!irq_resources) { ++ error = -ENOMEM; ++ goto cleanup_msi_irqs; ++ } ++ ++ for (i = 0; i < irq_count; i++) { ++ mc_dev_irq = &irq_resources[i]; ++ ++ /* ++ * NOTE: This mc_dev_irq's MSI addr/value pair will be set ++ * by the fsl_mc_msi_write_msg() callback ++ */ ++ mc_dev_irq->resource.type = res_pool->type; ++ mc_dev_irq->resource.data = mc_dev_irq; ++ mc_dev_irq->resource.parent_pool = res_pool; ++ INIT_LIST_HEAD(&mc_dev_irq->resource.node); ++ list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list); ++ } ++ ++ for_each_msi_entry(msi_desc, &mc_bus_dev->dev) { ++ mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index]; ++ mc_dev_irq->msi_desc = msi_desc; ++ mc_dev_irq->resource.id = msi_desc->irq; ++ } ++ ++ res_pool->max_count = irq_count; ++ res_pool->free_count = irq_count; ++ mc_bus->irq_resources = irq_resources; ++ return 0; ++ ++cleanup_msi_irqs: ++ fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); ++ return error; ++} ++EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool); ++ ++/** ++ * Teardown the interrupt pool associated with an fsl-mc bus. ++ * It frees the IRQs that were allocated to the pool, back to the GIC-ITS. ++ */ ++void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus) ++{ ++ struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; ++ struct fsl_mc_resource_pool *res_pool = ++ &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; ++ ++ if (!mc_bus->irq_resources) ++ return; ++ ++ if (res_pool->max_count == 0) ++ return; ++ ++ if (res_pool->free_count != res_pool->max_count) ++ return; ++ ++ INIT_LIST_HEAD(&res_pool->free_list); ++ res_pool->max_count = 0; ++ res_pool->free_count = 0; ++ mc_bus->irq_resources = NULL; ++ fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); ++} ++EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool); ++ ++/** ++ * Allocate the IRQs required by a given fsl-mc device. ++ */ ++int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev) ++{ ++ int i; ++ int irq_count; ++ int res_allocated_count = 0; ++ int error = -EINVAL; ++ struct fsl_mc_device_irq **irqs = NULL; ++ struct fsl_mc_bus *mc_bus; ++ struct fsl_mc_resource_pool *res_pool; ++ ++ if (mc_dev->irqs) ++ return -EINVAL; ++ ++ irq_count = mc_dev->obj_desc.irq_count; ++ if (irq_count == 0) ++ return -EINVAL; ++ ++ if (is_fsl_mc_bus_dprc(mc_dev)) ++ mc_bus = to_fsl_mc_bus(mc_dev); ++ else ++ mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); ++ ++ if (!mc_bus->irq_resources) ++ return -EINVAL; ++ ++ res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; ++ if (res_pool->free_count < irq_count) { ++ dev_err(&mc_dev->dev, ++ "Not able to allocate %u irqs for device\n", irq_count); ++ return -ENOSPC; ++ } ++ ++ irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]), ++ GFP_KERNEL); ++ if (!irqs) ++ return -ENOMEM; ++ ++ for (i = 0; i < irq_count; i++) { ++ struct fsl_mc_resource *resource; ++ ++ error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ, ++ &resource); ++ if (error < 0) ++ goto error_resource_alloc; ++ ++ irqs[i] = to_fsl_mc_irq(resource); ++ res_allocated_count++; ++ ++ irqs[i]->mc_dev = mc_dev; ++ irqs[i]->dev_irq_index = i; ++ } ++ ++ mc_dev->irqs = irqs; ++ return 0; ++ ++error_resource_alloc: ++ for (i = 0; i < res_allocated_count; i++) { ++ irqs[i]->mc_dev = NULL; ++ fsl_mc_resource_free(&irqs[i]->resource); ++ } ++ ++ return error; ++} ++EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs); ++ ++/* ++ * Frees the IRQs that were allocated for an fsl-mc device. ++ */ ++void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev) ++{ ++ int i; ++ int irq_count; ++ struct fsl_mc_bus *mc_bus; ++ struct fsl_mc_device_irq **irqs = mc_dev->irqs; ++ ++ if (!irqs) ++ return; ++ ++ irq_count = mc_dev->obj_desc.irq_count; ++ ++ if (is_fsl_mc_bus_dprc(mc_dev)) ++ mc_bus = to_fsl_mc_bus(mc_dev); ++ else ++ mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); ++ ++ if (!mc_bus->irq_resources) ++ return; ++ ++ for (i = 0; i < irq_count; i++) { ++ irqs[i]->mc_dev = NULL; ++ fsl_mc_resource_free(&irqs[i]->resource); ++ } ++ ++ mc_dev->irqs = NULL; ++} ++EXPORT_SYMBOL_GPL(fsl_mc_free_irqs); ++ ++void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev) ++{ ++ int pool_type; ++ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); ++ ++ for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) { ++ struct fsl_mc_resource_pool *res_pool = ++ &mc_bus->resource_pools[pool_type]; ++ ++ res_pool->type = pool_type; ++ res_pool->max_count = 0; ++ res_pool->free_count = 0; ++ res_pool->mc_bus = mc_bus; ++ INIT_LIST_HEAD(&res_pool->free_list); ++ mutex_init(&res_pool->mutex); ++ } ++} ++EXPORT_SYMBOL_GPL(fsl_mc_init_all_resource_pools); ++ ++static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev, ++ enum fsl_mc_pool_type pool_type) ++{ ++ struct fsl_mc_resource *resource; ++ struct fsl_mc_resource *next; ++ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); ++ struct fsl_mc_resource_pool *res_pool = ++ &mc_bus->resource_pools[pool_type]; ++ int free_count = 0; ++ ++ list_for_each_entry_safe(resource, next, &res_pool->free_list, node) { ++ free_count++; ++ devm_kfree(&mc_bus_dev->dev, resource); ++ } ++} ++ ++void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev) ++{ ++ int pool_type; ++ ++ for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) ++ fsl_mc_cleanup_resource_pool(mc_bus_dev, pool_type); ++} ++EXPORT_SYMBOL_GPL(fsl_mc_cleanup_all_resource_pools); ++ ++/** ++ * fsl_mc_allocator_probe - callback invoked when an allocatable device is ++ * being added to the system ++ */ ++static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev) ++{ ++ enum fsl_mc_pool_type pool_type; ++ struct fsl_mc_device *mc_bus_dev; ++ struct fsl_mc_bus *mc_bus; ++ int error; ++ ++ if (!fsl_mc_is_allocatable(mc_dev)) ++ return -EINVAL; ++ ++ mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); ++ if (!dev_is_fsl_mc(&mc_bus_dev->dev)) ++ return -EINVAL; ++ ++ mc_bus = to_fsl_mc_bus(mc_bus_dev); ++ error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type); ++ if (error < 0) ++ return error; ++ ++ error = fsl_mc_resource_pool_add_device(mc_bus, pool_type, mc_dev); ++ if (error < 0) ++ return error; ++ ++ dev_dbg(&mc_dev->dev, ++ "Allocatable fsl-mc device bound to fsl_mc_allocator driver"); ++ return 0; ++} ++ ++/** ++ * fsl_mc_allocator_remove - callback invoked when an allocatable device is ++ * being removed from the system ++ */ ++static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev) ++{ ++ int error; ++ ++ if (!fsl_mc_is_allocatable(mc_dev)) ++ return -EINVAL; ++ ++ if (mc_dev->resource) { ++ error = fsl_mc_resource_pool_remove_device(mc_dev); ++ if (error < 0) ++ return error; ++ } ++ ++ dev_dbg(&mc_dev->dev, ++ "Allocatable fsl-mc device unbound from fsl_mc_allocator driver"); ++ return 0; ++} ++ ++static const struct fsl_mc_device_id match_id_table[] = { ++ { ++ .vendor = FSL_MC_VENDOR_FREESCALE, ++ .obj_type = "dpbp", ++ }, ++ { ++ .vendor = FSL_MC_VENDOR_FREESCALE, ++ .obj_type = "dpmcp", ++ }, ++ { ++ .vendor = FSL_MC_VENDOR_FREESCALE, ++ .obj_type = "dpcon", ++ }, ++ {.vendor = 0x0}, ++}; ++ ++static struct fsl_mc_driver fsl_mc_allocator_driver = { ++ .driver = { ++ .name = "fsl_mc_allocator", ++ .pm = NULL, ++ }, ++ .match_id_table = match_id_table, ++ .probe = fsl_mc_allocator_probe, ++ .remove = fsl_mc_allocator_remove, ++}; ++ ++int __init fsl_mc_allocator_driver_init(void) ++{ ++ return fsl_mc_driver_register(&fsl_mc_allocator_driver); ++} ++ ++void fsl_mc_allocator_driver_exit(void) ++{ ++ fsl_mc_driver_unregister(&fsl_mc_allocator_driver); ++} +--- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c ++++ /dev/null +@@ -1,920 +0,0 @@ +-/* +- * Freescale Management Complex (MC) bus driver +- * +- * Copyright (C) 2014 Freescale Semiconductor, Inc. +- * Author: German Rivera <German.Rivera@freescale.com> +- * +- * 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 <linux/module.h> +-#include <linux/of_device.h> +-#include <linux/of_address.h> +-#include <linux/ioport.h> +-#include <linux/slab.h> +-#include <linux/limits.h> +-#include <linux/bitops.h> +-#include <linux/msi.h> +-#include <linux/dma-mapping.h> +-#include "../include/mc-bus.h" +-#include "../include/dpmng.h" +-#include "../include/mc-sys.h" +- +-#include "fsl-mc-private.h" +-#include "dprc-cmd.h" +- +-static struct kmem_cache *mc_dev_cache; +- +-/** +- * Default DMA mask for devices on a fsl-mc bus +- */ +-#define FSL_MC_DEFAULT_DMA_MASK (~0ULL) +- +-/** +- * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device +- * @root_mc_bus_dev: MC object device representing the root DPRC +- * @num_translation_ranges: number of entries in addr_translation_ranges +- * @translation_ranges: array of bus to system address translation ranges +- */ +-struct fsl_mc { +- struct fsl_mc_device *root_mc_bus_dev; +- u8 num_translation_ranges; +- struct fsl_mc_addr_translation_range *translation_ranges; +-}; +- +-/** +- * struct fsl_mc_addr_translation_range - bus to system address translation +- * range +- * @mc_region_type: Type of MC region for the range being translated +- * @start_mc_offset: Start MC offset of the range being translated +- * @end_mc_offset: MC offset of the first byte after the range (last MC +- * offset of the range is end_mc_offset - 1) +- * @start_phys_addr: system physical address corresponding to start_mc_addr +- */ +-struct fsl_mc_addr_translation_range { +- enum dprc_region_type mc_region_type; +- u64 start_mc_offset; +- u64 end_mc_offset; +- phys_addr_t start_phys_addr; +-}; +- +-/** +- * fsl_mc_bus_match - device to driver matching callback +- * @dev: the MC object device structure to match against +- * @drv: the device driver to search for matching MC object device id +- * structures +- * +- * Returns 1 on success, 0 otherwise. +- */ +-static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv) +-{ +- const struct fsl_mc_device_id *id; +- struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); +- struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv); +- bool found = false; +- +- if (WARN_ON(!fsl_mc_bus_exists())) +- goto out; +- +- if (!mc_drv->match_id_table) +- goto out; +- +- /* +- * If the object is not 'plugged' don't match. +- * Only exception is the root DPRC, which is a special case. +- */ +- if ((mc_dev->obj_desc.state & DPRC_OBJ_STATE_PLUGGED) == 0 && +- !fsl_mc_is_root_dprc(&mc_dev->dev)) +- goto out; +- +- /* +- * Traverse the match_id table of the given driver, trying to find +- * a matching for the given MC object device. +- */ +- for (id = mc_drv->match_id_table; id->vendor != 0x0; id++) { +- if (id->vendor == mc_dev->obj_desc.vendor && +- strcmp(id->obj_type, mc_dev->obj_desc.type) == 0) { +- found = true; +- +- break; +- } +- } +- +-out: +- dev_dbg(dev, "%smatched\n", found ? "" : "not "); +- return found; +-} +- +-/** +- * fsl_mc_bus_uevent - callback invoked when a device is added +- */ +-static int fsl_mc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) +-{ +- struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); +- +- if (add_uevent_var(env, "MODALIAS=fsl-mc:v%08Xd%s", +- mc_dev->obj_desc.vendor, +- mc_dev->obj_desc.type)) +- return -ENOMEM; +- +- return 0; +-} +- +-static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, +- char *buf) +-{ +- struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); +- +- return sprintf(buf, "fsl-mc:v%08Xd%s\n", mc_dev->obj_desc.vendor, +- mc_dev->obj_desc.type); +-} +-static DEVICE_ATTR_RO(modalias); +- +-static struct attribute *fsl_mc_dev_attrs[] = { +- &dev_attr_modalias.attr, +- NULL, +-}; +- +-ATTRIBUTE_GROUPS(fsl_mc_dev); +- +-struct bus_type fsl_mc_bus_type = { +- .name = "fsl-mc", +- .match = fsl_mc_bus_match, +- .uevent = fsl_mc_bus_uevent, +- .dev_groups = fsl_mc_dev_groups, +-}; +-EXPORT_SYMBOL_GPL(fsl_mc_bus_type); +- +-static atomic_t root_dprc_count = ATOMIC_INIT(0); +- +-static int fsl_mc_driver_probe(struct device *dev) +-{ +- struct fsl_mc_driver *mc_drv; +- struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); +- int error; +- +- if (WARN_ON(!dev->driver)) +- return -EINVAL; +- +- mc_drv = to_fsl_mc_driver(dev->driver); +- if (WARN_ON(!mc_drv->probe)) +- return -EINVAL; +- +- error = mc_drv->probe(mc_dev); +- if (error < 0) { +- dev_err(dev, "MC object device probe callback failed: %d\n", +- error); +- return error; +- } +- +- return 0; +-} +- +-static int fsl_mc_driver_remove(struct device *dev) +-{ +- struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); +- struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); +- int error; +- +- if (WARN_ON(!dev->driver)) +- return -EINVAL; +- +- error = mc_drv->remove(mc_dev); +- if (error < 0) { +- dev_err(dev, +- "MC object device remove callback failed: %d\n", +- error); +- return error; +- } +- +- return 0; +-} +- +-static void fsl_mc_driver_shutdown(struct device *dev) +-{ +- struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); +- struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); +- +- mc_drv->shutdown(mc_dev); +-} +- +-/** +- * __fsl_mc_driver_register - registers a child device driver with the +- * MC bus +- * +- * This function is implicitly invoked from the registration function of +- * fsl_mc device drivers, which is generated by the +- * module_fsl_mc_driver() macro. +- */ +-int __fsl_mc_driver_register(struct fsl_mc_driver *mc_driver, +- struct module *owner) +-{ +- int error; +- +- mc_driver->driver.owner = owner; +- mc_driver->driver.bus = &fsl_mc_bus_type; +- +- if (mc_driver->probe) +- mc_driver->driver.probe = fsl_mc_driver_probe; +- +- if (mc_driver->remove) +- mc_driver->driver.remove = fsl_mc_driver_remove; +- +- if (mc_driver->shutdown) +- mc_driver->driver.shutdown = fsl_mc_driver_shutdown; +- +- error = driver_register(&mc_driver->driver); +- if (error < 0) { +- pr_err("driver_register() failed for %s: %d\n", +- mc_driver->driver.name, error); +- return error; +- } +- +- pr_info("MC object device driver %s registered\n", +- mc_driver->driver.name); +- return 0; +-} +-EXPORT_SYMBOL_GPL(__fsl_mc_driver_register); +- +-/** +- * fsl_mc_driver_unregister - unregisters a device driver from the +- * MC bus +- */ +-void fsl_mc_driver_unregister(struct fsl_mc_driver *mc_driver) +-{ +- driver_unregister(&mc_driver->driver); +-} +-EXPORT_SYMBOL_GPL(fsl_mc_driver_unregister); +- +-/** +- * fsl_mc_bus_exists - check if a root dprc exists +- */ +-bool fsl_mc_bus_exists(void) +-{ +- return atomic_read(&root_dprc_count) > 0; +-} +-EXPORT_SYMBOL_GPL(fsl_mc_bus_exists); +- +-/** +- * fsl_mc_get_root_dprc - function to traverse to the root dprc +- */ +-void fsl_mc_get_root_dprc(struct device *dev, +- struct device **root_dprc_dev) +-{ +- if (WARN_ON(!dev)) { +- *root_dprc_dev = NULL; +- } else if (WARN_ON(!dev_is_fsl_mc(dev))) { +- *root_dprc_dev = NULL; +- } else { +- *root_dprc_dev = dev; +- while (dev_is_fsl_mc((*root_dprc_dev)->parent)) +- *root_dprc_dev = (*root_dprc_dev)->parent; +- } +-} +-EXPORT_SYMBOL_GPL(fsl_mc_get_root_dprc); +- +-static int get_dprc_attr(struct fsl_mc_io *mc_io, +- int container_id, struct dprc_attributes *attr) +-{ +- u16 dprc_handle; +- int error; +- +- error = dprc_open(mc_io, 0, container_id, &dprc_handle); +- if (error < 0) { +- dev_err(mc_io->dev, "dprc_open() failed: %d\n", error); +- return error; +- } +- +- memset(attr, 0, sizeof(struct dprc_attributes)); +- error = dprc_get_attributes(mc_io, 0, dprc_handle, attr); +- if (error < 0) { +- dev_err(mc_io->dev, "dprc_get_attributes() failed: %d\n", +- error); +- goto common_cleanup; +- } +- +- error = 0; +- +-common_cleanup: +- (void)dprc_close(mc_io, 0, dprc_handle); +- return error; +-} +- +-static int get_dprc_icid(struct fsl_mc_io *mc_io, +- int container_id, u16 *icid) +-{ +- struct dprc_attributes attr; +- int error; +- +- error = get_dprc_attr(mc_io, container_id, &attr); +- if (error == 0) +- *icid = attr.icid; +- +- return error; +-} +- +-static int get_dprc_version(struct fsl_mc_io *mc_io, +- int container_id, u16 *major, u16 *minor) +-{ +- struct dprc_attributes attr; +- int error; +- +- error = get_dprc_attr(mc_io, container_id, &attr); +- if (error == 0) { +- *major = attr.version.major; +- *minor = attr.version.minor; +- } +- +- return error; +-} +- +-static int translate_mc_addr(struct fsl_mc_device *mc_dev, +- enum dprc_region_type mc_region_type, +- u64 mc_offset, phys_addr_t *phys_addr) +-{ +- int i; +- struct device *root_dprc_dev; +- struct fsl_mc *mc; +- +- fsl_mc_get_root_dprc(&mc_dev->dev, &root_dprc_dev); +- if (WARN_ON(!root_dprc_dev)) +- return -EINVAL; +- mc = dev_get_drvdata(root_dprc_dev->parent); +- +- if (mc->num_translation_ranges == 0) { +- /* +- * Do identity mapping: +- */ +- *phys_addr = mc_offset; +- return 0; +- } +- +- for (i = 0; i < mc->num_translation_ranges; i++) { +- struct fsl_mc_addr_translation_range *range = +- &mc->translation_ranges[i]; +- +- if (mc_region_type == range->mc_region_type && +- mc_offset >= range->start_mc_offset && +- mc_offset < range->end_mc_offset) { +- *phys_addr = range->start_phys_addr + +- (mc_offset - range->start_mc_offset); +- return 0; +- } +- } +- +- return -EFAULT; +-} +- +-static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev, +- struct fsl_mc_device *mc_bus_dev) +-{ +- int i; +- int error; +- struct resource *regions; +- struct dprc_obj_desc *obj_desc = &mc_dev->obj_desc; +- struct device *parent_dev = mc_dev->dev.parent; +- enum dprc_region_type mc_region_type; +- +- if (strcmp(obj_desc->type, "dprc") == 0 || +- strcmp(obj_desc->type, "dpmcp") == 0) { +- mc_region_type = DPRC_REGION_TYPE_MC_PORTAL; +- } else if (strcmp(obj_desc->type, "dpio") == 0) { +- mc_region_type = DPRC_REGION_TYPE_QBMAN_PORTAL; +- } else { +- /* +- * This function should not have been called for this MC object +- * type, as this object type is not supposed to have MMIO +- * regions +- */ +- WARN_ON(true); +- return -EINVAL; +- } +- +- regions = kmalloc_array(obj_desc->region_count, +- sizeof(regions[0]), GFP_KERNEL); +- if (!regions) +- return -ENOMEM; +- +- for (i = 0; i < obj_desc->region_count; i++) { +- struct dprc_region_desc region_desc; +- +- error = dprc_get_obj_region(mc_bus_dev->mc_io, +- 0, +- mc_bus_dev->mc_handle, +- obj_desc->type, +- obj_desc->id, i, ®ion_desc); +- if (error < 0) { +- dev_err(parent_dev, +- "dprc_get_obj_region() failed: %d\n", error); +- goto error_cleanup_regions; +- } +- +- WARN_ON(region_desc.size == 0); +- error = translate_mc_addr(mc_dev, mc_region_type, +- region_desc.base_offset, +- ®ions[i].start); +- if (error < 0) { +- dev_err(parent_dev, +- "Invalid MC offset: %#x (for %s.%d\'s region %d)\n", +- region_desc.base_offset, +- obj_desc->type, obj_desc->id, i); +- goto error_cleanup_regions; +- } +- +- regions[i].end = regions[i].start + region_desc.size - 1; +- regions[i].name = "fsl-mc object MMIO region"; +- regions[i].flags = IORESOURCE_IO; +- if (region_desc.flags & DPRC_REGION_CACHEABLE) +- regions[i].flags |= IORESOURCE_CACHEABLE; +- } +- +- mc_dev->regions = regions; +- return 0; +- +-error_cleanup_regions: +- kfree(regions); +- return error; +-} +- +-/** +- * fsl_mc_is_root_dprc - function to check if a given device is a root dprc +- */ +-bool fsl_mc_is_root_dprc(struct device *dev) +-{ +- struct device *root_dprc_dev; +- +- fsl_mc_get_root_dprc(dev, &root_dprc_dev); +- if (!root_dprc_dev) +- return false; +- return dev == root_dprc_dev; +-} +- +-/** +- * Add a newly discovered MC object device to be visible in Linux +- */ +-int fsl_mc_device_add(struct dprc_obj_desc *obj_desc, +- struct fsl_mc_io *mc_io, +- struct device *parent_dev, +- struct fsl_mc_device **new_mc_dev) +-{ +- int error; +- struct fsl_mc_device *mc_dev = NULL; +- struct fsl_mc_bus *mc_bus = NULL; +- struct fsl_mc_device *parent_mc_dev; +- +- if (dev_is_fsl_mc(parent_dev)) +- parent_mc_dev = to_fsl_mc_device(parent_dev); +- else +- parent_mc_dev = NULL; +- +- if (strcmp(obj_desc->type, "dprc") == 0) { +- /* +- * Allocate an MC bus device object: +- */ +- mc_bus = devm_kzalloc(parent_dev, sizeof(*mc_bus), GFP_KERNEL); +- if (!mc_bus) +- return -ENOMEM; +- +- mc_dev = &mc_bus->mc_dev; +- } else { +- /* +- * Allocate a regular fsl_mc_device object: +- */ +- mc_dev = kmem_cache_zalloc(mc_dev_cache, GFP_KERNEL); +- if (!mc_dev) +- return -ENOMEM; +- } +- +- mc_dev->obj_desc = *obj_desc; +- mc_dev->mc_io = mc_io; +- device_initialize(&mc_dev->dev); +- mc_dev->dev.parent = parent_dev; +- mc_dev->dev.bus = &fsl_mc_bus_type; +- dev_set_name(&mc_dev->dev, "%s.%d", obj_desc->type, obj_desc->id); +- +- if (strcmp(obj_desc->type, "dprc") == 0) { +- struct fsl_mc_io *mc_io2; +- +- mc_dev->flags |= FSL_MC_IS_DPRC; +- +- /* +- * To get the DPRC's ICID, we need to open the DPRC +- * in get_dprc_icid(). For child DPRCs, we do so using the +- * parent DPRC's MC portal instead of the child DPRC's MC +- * portal, in case the child DPRC is already opened with +- * its own portal (e.g., the DPRC used by AIOP). +- * +- * NOTE: There cannot be more than one active open for a +- * given MC object, using the same MC portal. +- */ +- if (parent_mc_dev) { +- /* +- * device being added is a child DPRC device +- */ +- mc_io2 = parent_mc_dev->mc_io; +- } else { +- /* +- * device being added is the root DPRC device +- */ +- if (WARN_ON(!mc_io)) { +- error = -EINVAL; +- goto error_cleanup_dev; +- } +- +- mc_io2 = mc_io; +- +- atomic_inc(&root_dprc_count); +- } +- +- error = get_dprc_icid(mc_io2, obj_desc->id, &mc_dev->icid); +- if (error < 0) +- goto error_cleanup_dev; +- } else { +- /* +- * A non-DPRC MC object device has to be a child of another +- * MC object (specifically a DPRC object) +- */ +- mc_dev->icid = parent_mc_dev->icid; +- mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK; +- mc_dev->dev.dma_mask = &mc_dev->dma_mask; +- dev_set_msi_domain(&mc_dev->dev, +- dev_get_msi_domain(&parent_mc_dev->dev)); +- } +- +- /* +- * Get MMIO regions for the device from the MC: +- * +- * NOTE: the root DPRC is a special case as its MMIO region is +- * obtained from the device tree +- */ +- if (parent_mc_dev && obj_desc->region_count != 0) { +- error = fsl_mc_device_get_mmio_regions(mc_dev, +- parent_mc_dev); +- if (error < 0) +- goto error_cleanup_dev; +- } +- +- /* Objects are coherent, unless 'no shareability' flag set. */ +- if (!(obj_desc->flags & DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY)) +- arch_setup_dma_ops(&mc_dev->dev, 0, 0, NULL, true); +- +- /* +- * The device-specific probe callback will get invoked by device_add() +- */ +- error = device_add(&mc_dev->dev); +- if (error < 0) { +- dev_err(parent_dev, +- "device_add() failed for device %s: %d\n", +- dev_name(&mc_dev->dev), error); +- goto error_cleanup_dev; +- } +- +- (void)get_device(&mc_dev->dev); +- dev_dbg(parent_dev, "Added MC object device %s\n", +- dev_name(&mc_dev->dev)); +- +- *new_mc_dev = mc_dev; +- return 0; +- +-error_cleanup_dev: +- kfree(mc_dev->regions); +- if (mc_bus) +- devm_kfree(parent_dev, mc_bus); +- else +- kmem_cache_free(mc_dev_cache, mc_dev); +- +- return error; +-} +-EXPORT_SYMBOL_GPL(fsl_mc_device_add); +- +-/** +- * fsl_mc_device_remove - Remove a MC object device from being visible to +- * Linux +- * +- * @mc_dev: Pointer to a MC object device object +- */ +-void fsl_mc_device_remove(struct fsl_mc_device *mc_dev) +-{ +- struct fsl_mc_bus *mc_bus = NULL; +- +- kfree(mc_dev->regions); +- +- /* +- * The device-specific remove callback will get invoked by device_del() +- */ +- device_del(&mc_dev->dev); +- put_device(&mc_dev->dev); +- +- if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) { +- mc_bus = to_fsl_mc_bus(mc_dev); +- +- if (fsl_mc_is_root_dprc(&mc_dev->dev)) { +- if (atomic_read(&root_dprc_count) > 0) +- atomic_dec(&root_dprc_count); +- else +- WARN_ON(1); +- } +- } +- +- if (mc_bus) +- devm_kfree(mc_dev->dev.parent, mc_bus); +- else +- kmem_cache_free(mc_dev_cache, mc_dev); +-} +-EXPORT_SYMBOL_GPL(fsl_mc_device_remove); +- +-static int parse_mc_ranges(struct device *dev, +- int *paddr_cells, +- int *mc_addr_cells, +- int *mc_size_cells, +- const __be32 **ranges_start, +- u8 *num_ranges) +-{ +- const __be32 *prop; +- int range_tuple_cell_count; +- int ranges_len; +- int tuple_len; +- struct device_node *mc_node = dev->of_node; +- +- *ranges_start = of_get_property(mc_node, "ranges", &ranges_len); +- if (!(*ranges_start) || !ranges_len) { +- dev_warn(dev, +- "missing or empty ranges property for device tree node '%s'\n", +- mc_node->name); +- +- *num_ranges = 0; +- return 0; +- } +- +- *paddr_cells = of_n_addr_cells(mc_node); +- +- prop = of_get_property(mc_node, "#address-cells", NULL); +- if (prop) +- *mc_addr_cells = be32_to_cpup(prop); +- else +- *mc_addr_cells = *paddr_cells; +- +- prop = of_get_property(mc_node, "#size-cells", NULL); +- if (prop) +- *mc_size_cells = be32_to_cpup(prop); +- else +- *mc_size_cells = of_n_size_cells(mc_node); +- +- range_tuple_cell_count = *paddr_cells + *mc_addr_cells + +- *mc_size_cells; +- +- tuple_len = range_tuple_cell_count * sizeof(__be32); +- if (ranges_len % tuple_len != 0) { +- dev_err(dev, "malformed ranges property '%s'\n", mc_node->name); +- return -EINVAL; +- } +- +- *num_ranges = ranges_len / tuple_len; +- return 0; +-} +- +-static int get_mc_addr_translation_ranges(struct device *dev, +- struct fsl_mc_addr_translation_range +- **ranges, +- u8 *num_ranges) +-{ +- int error; +- int paddr_cells; +- int mc_addr_cells; +- int mc_size_cells; +- int i; +- const __be32 *ranges_start; +- const __be32 *cell; +- +- error = parse_mc_ranges(dev, +- &paddr_cells, +- &mc_addr_cells, +- &mc_size_cells, +- &ranges_start, +- num_ranges); +- if (error < 0) +- return error; +- +- if (!(*num_ranges)) { +- /* +- * Missing or empty ranges property ("ranges;") for the +- * 'fsl,qoriq-mc' node. In this case, identity mapping +- * will be used. +- */ +- *ranges = NULL; +- return 0; +- } +- +- *ranges = devm_kcalloc(dev, *num_ranges, +- sizeof(struct fsl_mc_addr_translation_range), +- GFP_KERNEL); +- if (!(*ranges)) +- return -ENOMEM; +- +- cell = ranges_start; +- for (i = 0; i < *num_ranges; ++i) { +- struct fsl_mc_addr_translation_range *range = &(*ranges)[i]; +- +- range->mc_region_type = of_read_number(cell, 1); +- range->start_mc_offset = of_read_number(cell + 1, +- mc_addr_cells - 1); +- cell += mc_addr_cells; +- range->start_phys_addr = of_read_number(cell, paddr_cells); +- cell += paddr_cells; +- range->end_mc_offset = range->start_mc_offset + +- of_read_number(cell, mc_size_cells); +- +- cell += mc_size_cells; +- } +- +- return 0; +-} +- +-/** +- * fsl_mc_bus_probe - callback invoked when the root MC bus is being +- * added +- */ +-static int fsl_mc_bus_probe(struct platform_device *pdev) +-{ +- struct dprc_obj_desc obj_desc; +- int error; +- struct fsl_mc *mc; +- struct fsl_mc_device *mc_bus_dev = NULL; +- struct fsl_mc_io *mc_io = NULL; +- int container_id; +- phys_addr_t mc_portal_phys_addr; +- u32 mc_portal_size; +- struct mc_version mc_version; +- struct resource res; +- +- dev_info(&pdev->dev, "Root MC bus device probed"); +- +- mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL); +- if (!mc) +- return -ENOMEM; +- +- platform_set_drvdata(pdev, mc); +- +- /* +- * Get physical address of MC portal for the root DPRC: +- */ +- error = of_address_to_resource(pdev->dev.of_node, 0, &res); +- if (error < 0) { +- dev_err(&pdev->dev, +- "of_address_to_resource() failed for %s\n", +- pdev->dev.of_node->full_name); +- return error; +- } +- +- mc_portal_phys_addr = res.start; +- mc_portal_size = resource_size(&res); +- error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr, +- mc_portal_size, NULL, +- FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, &mc_io); +- if (error < 0) +- return error; +- +- error = mc_get_version(mc_io, 0, &mc_version); +- if (error != 0) { +- dev_err(&pdev->dev, +- "mc_get_version() failed with error %d\n", error); +- goto error_cleanup_mc_io; +- } +- +- dev_info(&pdev->dev, +- "Freescale Management Complex Firmware version: %u.%u.%u\n", +- mc_version.major, mc_version.minor, mc_version.revision); +- +- error = get_mc_addr_translation_ranges(&pdev->dev, +- &mc->translation_ranges, +- &mc->num_translation_ranges); +- if (error < 0) +- goto error_cleanup_mc_io; +- +- error = dpmng_get_container_id(mc_io, 0, &container_id); +- if (error < 0) { +- dev_err(&pdev->dev, +- "dpmng_get_container_id() failed: %d\n", error); +- goto error_cleanup_mc_io; +- } +- +- memset(&obj_desc, 0, sizeof(struct dprc_obj_desc)); +- error = get_dprc_version(mc_io, container_id, +- &obj_desc.ver_major, &obj_desc.ver_minor); +- if (error < 0) +- goto error_cleanup_mc_io; +- +- obj_desc.vendor = FSL_MC_VENDOR_FREESCALE; +- strcpy(obj_desc.type, "dprc"); +- obj_desc.id = container_id; +- obj_desc.irq_count = 1; +- obj_desc.region_count = 0; +- +- error = fsl_mc_device_add(&obj_desc, mc_io, &pdev->dev, &mc_bus_dev); +- if (error < 0) +- goto error_cleanup_mc_io; +- +- mc->root_mc_bus_dev = mc_bus_dev; +- return 0; +- +-error_cleanup_mc_io: +- fsl_destroy_mc_io(mc_io); +- return error; +-} +- +-/** +- * fsl_mc_bus_remove - callback invoked when the root MC bus is being +- * removed +- */ +-static int fsl_mc_bus_remove(struct platform_device *pdev) +-{ +- struct fsl_mc *mc = platform_get_drvdata(pdev); +- +- if (WARN_ON(!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev))) +- return -EINVAL; +- +- fsl_mc_device_remove(mc->root_mc_bus_dev); +- +- fsl_destroy_mc_io(mc->root_mc_bus_dev->mc_io); +- mc->root_mc_bus_dev->mc_io = NULL; +- +- dev_info(&pdev->dev, "Root MC bus device removed"); +- return 0; +-} +- +-static const struct of_device_id fsl_mc_bus_match_table[] = { +- {.compatible = "fsl,qoriq-mc",}, +- {}, +-}; +- +-MODULE_DEVICE_TABLE(of, fsl_mc_bus_match_table); +- +-static struct platform_driver fsl_mc_bus_driver = { +- .driver = { +- .name = "fsl_mc_bus", +- .pm = NULL, +- .of_match_table = fsl_mc_bus_match_table, +- }, +- .probe = fsl_mc_bus_probe, +- .remove = fsl_mc_bus_remove, +-}; +- +-static int __init fsl_mc_bus_driver_init(void) +-{ +- int error; +- +- mc_dev_cache = kmem_cache_create("fsl_mc_device", +- sizeof(struct fsl_mc_device), 0, 0, +- NULL); +- if (!mc_dev_cache) { +- pr_err("Could not create fsl_mc_device cache\n"); +- return -ENOMEM; +- } +- +- error = bus_register(&fsl_mc_bus_type); +- if (error < 0) { +- pr_err("fsl-mc bus type registration failed: %d\n", error); +- goto error_cleanup_cache; +- } +- +- pr_info("fsl-mc bus type registered\n"); +- +- error = platform_driver_register(&fsl_mc_bus_driver); +- if (error < 0) { +- pr_err("platform_driver_register() failed: %d\n", error); +- goto error_cleanup_bus; +- } +- +- error = dprc_driver_init(); +- if (error < 0) +- goto error_cleanup_driver; +- +- error = fsl_mc_allocator_driver_init(); +- if (error < 0) +- goto error_cleanup_dprc_driver; +- +- error = its_fsl_mc_msi_init(); +- if (error < 0) +- goto error_cleanup_mc_allocator; +- +- return 0; +- +-error_cleanup_mc_allocator: +- fsl_mc_allocator_driver_exit(); +- +-error_cleanup_dprc_driver: +- dprc_driver_exit(); +- +-error_cleanup_driver: +- platform_driver_unregister(&fsl_mc_bus_driver); +- +-error_cleanup_bus: +- bus_unregister(&fsl_mc_bus_type); +- +-error_cleanup_cache: +- kmem_cache_destroy(mc_dev_cache); +- return error; +-} +-postcore_initcall(fsl_mc_bus_driver_init); +--- /dev/null ++++ b/drivers/bus/fsl-mc/fsl-mc-bus.c +@@ -0,0 +1,1151 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Freescale Management Complex (MC) bus driver ++ * ++ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. ++ * Author: German Rivera <German.Rivera@freescale.com> ++ * ++ */ ++ ++#define pr_fmt(fmt) "fsl-mc: " fmt ++ ++#include <linux/module.h> ++#include <linux/of_device.h> ++#include <linux/of_address.h> ++#include <linux/ioport.h> ++#include <linux/slab.h> ++#include <linux/limits.h> ++#include <linux/bitops.h> ++#include <linux/msi.h> ++#include <linux/dma-mapping.h> ++#include <linux/fsl/mc.h> ++ ++#include "fsl-mc-private.h" ++ ++/** ++ * Default DMA mask for devices on a fsl-mc bus ++ */ ++#define FSL_MC_DEFAULT_DMA_MASK (~0ULL) ++ ++/** ++ * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device ++ * @root_mc_bus_dev: fsl-mc device representing the root DPRC ++ * @num_translation_ranges: number of entries in addr_translation_ranges ++ * @translation_ranges: array of bus to system address translation ranges ++ */ ++struct fsl_mc { ++ struct fsl_mc_device *root_mc_bus_dev; ++ u8 num_translation_ranges; ++ struct fsl_mc_addr_translation_range *translation_ranges; ++}; ++ ++/** ++ * struct fsl_mc_addr_translation_range - bus to system address translation ++ * range ++ * @mc_region_type: Type of MC region for the range being translated ++ * @start_mc_offset: Start MC offset of the range being translated ++ * @end_mc_offset: MC offset of the first byte after the range (last MC ++ * offset of the range is end_mc_offset - 1) ++ * @start_phys_addr: system physical address corresponding to start_mc_addr ++ */ ++struct fsl_mc_addr_translation_range { ++ enum dprc_region_type mc_region_type; ++ u64 start_mc_offset; ++ u64 end_mc_offset; ++ phys_addr_t start_phys_addr; ++}; ++ ++/** ++ * struct mc_version ++ * @major: Major version number: incremented on API compatibility changes ++ * @minor: Minor version number: incremented on API additions (that are ++ * backward compatible); reset when major version is incremented ++ * @revision: Internal revision number: incremented on implementation changes ++ * and/or bug fixes that have no impact on API ++ */ ++struct mc_version { ++ u32 major; ++ u32 minor; ++ u32 revision; ++}; ++ ++/** ++ * fsl_mc_bus_match - device to driver matching callback ++ * @dev: the fsl-mc device to match against ++ * @drv: the device driver to search for matching fsl-mc object type ++ * structures ++ * ++ * Returns 1 on success, 0 otherwise. ++ */ ++static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv) ++{ ++ const struct fsl_mc_device_id *id; ++ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); ++ struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv); ++ bool found = false; ++ ++ /* When driver_override is set, only bind to the matching driver */ ++ if (mc_dev->driver_override) { ++ found = !strcmp(mc_dev->driver_override, mc_drv->driver.name); ++ goto out; ++ } ++ ++ if (!mc_drv->match_id_table) ++ goto out; ++ ++ /* ++ * If the object is not 'plugged' don't match. ++ * Only exception is the root DPRC, which is a special case. ++ */ ++ if ((mc_dev->obj_desc.state & FSL_MC_OBJ_STATE_PLUGGED) == 0 && ++ !fsl_mc_is_root_dprc(&mc_dev->dev)) ++ goto out; ++ ++ /* ++ * Traverse the match_id table of the given driver, trying to find ++ * a matching for the given device. ++ */ ++ for (id = mc_drv->match_id_table; id->vendor != 0x0; id++) { ++ if (id->vendor == mc_dev->obj_desc.vendor && ++ strcmp(id->obj_type, mc_dev->obj_desc.type) == 0) { ++ found = true; ++ ++ break; ++ } ++ } ++ ++out: ++ dev_dbg(dev, "%smatched\n", found ? "" : "not "); ++ return found; ++} ++ ++/** ++ * fsl_mc_bus_uevent - callback invoked when a device is added ++ */ ++static int fsl_mc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) ++{ ++ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); ++ ++ if (add_uevent_var(env, "MODALIAS=fsl-mc:v%08Xd%s", ++ mc_dev->obj_desc.vendor, ++ mc_dev->obj_desc.type)) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); ++ ++ return sprintf(buf, "fsl-mc:v%08Xd%s\n", mc_dev->obj_desc.vendor, ++ mc_dev->obj_desc.type); ++} ++static DEVICE_ATTR_RO(modalias); ++ ++static ssize_t rescan_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct fsl_mc_device *root_mc_dev; ++ struct fsl_mc_bus *root_mc_bus; ++ unsigned long val; ++ ++ if (!fsl_mc_is_root_dprc(dev)) ++ return -EINVAL; ++ ++ root_mc_dev = to_fsl_mc_device(dev); ++ root_mc_bus = to_fsl_mc_bus(root_mc_dev); ++ ++ if (kstrtoul(buf, 0, &val) < 0) ++ return -EINVAL; ++ ++ if (val) { ++ mutex_lock(&root_mc_bus->scan_mutex); ++ dprc_scan_objects(root_mc_dev, NULL, NULL); ++ mutex_unlock(&root_mc_bus->scan_mutex); ++ } ++ ++ return count; ++} ++static DEVICE_ATTR_WO(rescan); ++ ++static ssize_t driver_override_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); ++ const char *driver_override, *old = mc_dev->driver_override; ++ char *cp; ++ ++ if (WARN_ON(dev->bus != &fsl_mc_bus_type)) ++ return -EINVAL; ++ ++ if (count >= (PAGE_SIZE - 1)) ++ return -EINVAL; ++ ++ driver_override = kstrndup(buf, count, GFP_KERNEL); ++ if (!driver_override) ++ return -ENOMEM; ++ ++ cp = strchr(driver_override, '\n'); ++ if (cp) ++ *cp = '\0'; ++ ++ if (strlen(driver_override)) { ++ mc_dev->driver_override = driver_override; ++ } else { ++ kfree(driver_override); ++ mc_dev->driver_override = NULL; ++ } ++ ++ kfree(old); ++ ++ return count; ++} ++ ++static ssize_t driver_override_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); ++ ++ return snprintf(buf, PAGE_SIZE, "%s\n", mc_dev->driver_override); ++} ++static DEVICE_ATTR_RW(driver_override); ++ ++static struct attribute *fsl_mc_dev_attrs[] = { ++ &dev_attr_modalias.attr, ++ &dev_attr_rescan.attr, ++ &dev_attr_driver_override.attr, ++ NULL, ++}; ++ ++ATTRIBUTE_GROUPS(fsl_mc_dev); ++ ++static int scan_fsl_mc_bus(struct device *dev, void *data) ++{ ++ struct fsl_mc_device *root_mc_dev; ++ struct fsl_mc_bus *root_mc_bus; ++ ++ if (!fsl_mc_is_root_dprc(dev)) ++ goto exit; ++ ++ root_mc_dev = to_fsl_mc_device(dev); ++ root_mc_bus = to_fsl_mc_bus(root_mc_dev); ++ mutex_lock(&root_mc_bus->scan_mutex); ++ dprc_scan_objects(root_mc_dev, NULL, NULL); ++ mutex_unlock(&root_mc_bus->scan_mutex); ++ ++exit: ++ return 0; ++} ++ ++static ssize_t bus_rescan_store(struct bus_type *bus, ++ const char *buf, size_t count) ++{ ++ unsigned long val; ++ ++ if (kstrtoul(buf, 0, &val) < 0) ++ return -EINVAL; ++ ++ if (val) ++ bus_for_each_dev(bus, NULL, NULL, scan_fsl_mc_bus); ++ ++ return count; ++} ++static BUS_ATTR(rescan, 0220, NULL, bus_rescan_store); ++ ++static struct attribute *fsl_mc_bus_attrs[] = { ++ &bus_attr_rescan.attr, ++ NULL, ++}; ++ ++static const struct attribute_group fsl_mc_bus_group = { ++ .attrs = fsl_mc_bus_attrs, ++}; ++ ++static const struct attribute_group *fsl_mc_bus_groups[] = { ++ &fsl_mc_bus_group, ++ NULL, ++}; ++ ++struct bus_type fsl_mc_bus_type = { ++ .name = "fsl-mc", ++ .match = fsl_mc_bus_match, ++ .uevent = fsl_mc_bus_uevent, ++ .dev_groups = fsl_mc_dev_groups, ++ .bus_groups = fsl_mc_bus_groups, ++}; ++EXPORT_SYMBOL_GPL(fsl_mc_bus_type); ++ ++struct device_type fsl_mc_bus_dprc_type = { ++ .name = "fsl_mc_bus_dprc" ++}; ++ ++struct device_type fsl_mc_bus_dpni_type = { ++ .name = "fsl_mc_bus_dpni" ++}; ++ ++struct device_type fsl_mc_bus_dpio_type = { ++ .name = "fsl_mc_bus_dpio" ++}; ++ ++struct device_type fsl_mc_bus_dpsw_type = { ++ .name = "fsl_mc_bus_dpsw" ++}; ++ ++struct device_type fsl_mc_bus_dpdmux_type = { ++ .name = "fsl_mc_bus_dpdmux" ++}; ++ ++struct device_type fsl_mc_bus_dpbp_type = { ++ .name = "fsl_mc_bus_dpbp" ++}; ++ ++struct device_type fsl_mc_bus_dpcon_type = { ++ .name = "fsl_mc_bus_dpcon" ++}; ++ ++struct device_type fsl_mc_bus_dpmcp_type = { ++ .name = "fsl_mc_bus_dpmcp" ++}; ++ ++struct device_type fsl_mc_bus_dpmac_type = { ++ .name = "fsl_mc_bus_dpmac" ++}; ++ ++struct device_type fsl_mc_bus_dprtc_type = { ++ .name = "fsl_mc_bus_dprtc" ++}; ++ ++struct device_type fsl_mc_bus_dpseci_type = { ++ .name = "fsl_mc_bus_dpseci" ++}; ++ ++struct device_type fsl_mc_bus_dpdcei_type = { ++ .name = "fsl_mc_bus_dpdcei" ++}; ++ ++struct device_type fsl_mc_bus_dpaiop_type = { ++ .name = "fsl_mc_bus_dpaiop" ++}; ++ ++struct device_type fsl_mc_bus_dpci_type = { ++ .name = "fsl_mc_bus_dpci" ++}; ++ ++struct device_type fsl_mc_bus_dpdmai_type = { ++ .name = "fsl_mc_bus_dpdmai" ++}; ++ ++static struct device_type *fsl_mc_get_device_type(const char *type) ++{ ++ static const struct { ++ struct device_type *dev_type; ++ const char *type; ++ } dev_types[] = { ++ { &fsl_mc_bus_dprc_type, "dprc" }, ++ { &fsl_mc_bus_dpni_type, "dpni" }, ++ { &fsl_mc_bus_dpio_type, "dpio" }, ++ { &fsl_mc_bus_dpsw_type, "dpsw" }, ++ { &fsl_mc_bus_dpdmux_type, "dpdmux" }, ++ { &fsl_mc_bus_dpbp_type, "dpbp" }, ++ { &fsl_mc_bus_dpcon_type, "dpcon" }, ++ { &fsl_mc_bus_dpmcp_type, "dpmcp" }, ++ { &fsl_mc_bus_dpmac_type, "dpmac" }, ++ { &fsl_mc_bus_dprtc_type, "dprtc" }, ++ { &fsl_mc_bus_dpseci_type, "dpseci" }, ++ { &fsl_mc_bus_dpdcei_type, "dpdcei" }, ++ { &fsl_mc_bus_dpaiop_type, "dpaiop" }, ++ { &fsl_mc_bus_dpci_type, "dpci" }, ++ { &fsl_mc_bus_dpdmai_type, "dpdmai" }, ++ { NULL, NULL } ++ }; ++ int i; ++ ++ for (i = 0; dev_types[i].dev_type; i++) ++ if (!strcmp(dev_types[i].type, type)) ++ return dev_types[i].dev_type; ++ ++ return NULL; ++} ++ ++static int fsl_mc_driver_probe(struct device *dev) ++{ ++ struct fsl_mc_driver *mc_drv; ++ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); ++ int error; ++ ++ mc_drv = to_fsl_mc_driver(dev->driver); ++ ++ error = mc_drv->probe(mc_dev); ++ if (error < 0) { ++ if (error != -EPROBE_DEFER) ++ dev_err(dev, "%s failed: %d\n", __func__, error); ++ return error; ++ } ++ ++ return 0; ++} ++ ++static int fsl_mc_driver_remove(struct device *dev) ++{ ++ struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); ++ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); ++ int error; ++ ++ error = mc_drv->remove(mc_dev); ++ if (error < 0) { ++ dev_err(dev, "%s failed: %d\n", __func__, error); ++ return error; ++ } ++ ++ return 0; ++} ++ ++static void fsl_mc_driver_shutdown(struct device *dev) ++{ ++ struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); ++ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); ++ ++ mc_drv->shutdown(mc_dev); ++} ++ ++/** ++ * __fsl_mc_driver_register - registers a child device driver with the ++ * MC bus ++ * ++ * This function is implicitly invoked from the registration function of ++ * fsl_mc device drivers, which is generated by the ++ * module_fsl_mc_driver() macro. ++ */ ++int __fsl_mc_driver_register(struct fsl_mc_driver *mc_driver, ++ struct module *owner) ++{ ++ int error; ++ ++ mc_driver->driver.owner = owner; ++ mc_driver->driver.bus = &fsl_mc_bus_type; ++ ++ if (mc_driver->probe) ++ mc_driver->driver.probe = fsl_mc_driver_probe; ++ ++ if (mc_driver->remove) ++ mc_driver->driver.remove = fsl_mc_driver_remove; ++ ++ if (mc_driver->shutdown) ++ mc_driver->driver.shutdown = fsl_mc_driver_shutdown; ++ ++ error = driver_register(&mc_driver->driver); ++ if (error < 0) { ++ pr_err("driver_register() failed for %s: %d\n", ++ mc_driver->driver.name, error); ++ return error; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(__fsl_mc_driver_register); ++ ++/** ++ * fsl_mc_driver_unregister - unregisters a device driver from the ++ * MC bus ++ */ ++void fsl_mc_driver_unregister(struct fsl_mc_driver *mc_driver) ++{ ++ driver_unregister(&mc_driver->driver); ++} ++EXPORT_SYMBOL_GPL(fsl_mc_driver_unregister); ++ ++/** ++ * mc_get_version() - Retrieves the Management Complex firmware ++ * version information ++ * @mc_io: Pointer to opaque I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @mc_ver_info: Returned version information structure ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++static int mc_get_version(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ struct mc_version *mc_ver_info) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ struct dpmng_rsp_get_version *rsp_params; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_VERSION, ++ cmd_flags, ++ 0); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ rsp_params = (struct dpmng_rsp_get_version *)cmd.params; ++ mc_ver_info->revision = le32_to_cpu(rsp_params->revision); ++ mc_ver_info->major = le32_to_cpu(rsp_params->version_major); ++ mc_ver_info->minor = le32_to_cpu(rsp_params->version_minor); ++ ++ return 0; ++} ++ ++/** ++ * fsl_mc_get_root_dprc - function to traverse to the root dprc ++ */ ++void fsl_mc_get_root_dprc(struct device *dev, ++ struct device **root_dprc_dev) ++{ ++ if (!dev) { ++ *root_dprc_dev = NULL; ++ } else if (!dev_is_fsl_mc(dev)) { ++ *root_dprc_dev = NULL; ++ } else { ++ *root_dprc_dev = dev; ++ while (dev_is_fsl_mc((*root_dprc_dev)->parent)) ++ *root_dprc_dev = (*root_dprc_dev)->parent; ++ } ++} ++EXPORT_SYMBOL_GPL(fsl_mc_get_root_dprc); ++ ++static int get_dprc_attr(struct fsl_mc_io *mc_io, ++ int container_id, struct dprc_attributes *attr) ++{ ++ u16 dprc_handle; ++ int error; ++ ++ error = dprc_open(mc_io, 0, container_id, &dprc_handle); ++ if (error < 0) { ++ dev_err(mc_io->dev, "dprc_open() failed: %d\n", error); ++ return error; ++ } ++ ++ memset(attr, 0, sizeof(struct dprc_attributes)); ++ error = dprc_get_attributes(mc_io, 0, dprc_handle, attr); ++ if (error < 0) { ++ dev_err(mc_io->dev, "dprc_get_attributes() failed: %d\n", ++ error); ++ goto common_cleanup; ++ } ++ ++ error = 0; ++ ++common_cleanup: ++ (void)dprc_close(mc_io, 0, dprc_handle); ++ return error; ++} ++ ++static int get_dprc_icid(struct fsl_mc_io *mc_io, ++ int container_id, u32 *icid) ++{ ++ struct dprc_attributes attr; ++ int error; ++ ++ error = get_dprc_attr(mc_io, container_id, &attr); ++ if (error == 0) ++ *icid = attr.icid; ++ ++ return error; ++} ++ ++static int translate_mc_addr(struct fsl_mc_device *mc_dev, ++ enum dprc_region_type mc_region_type, ++ u64 mc_offset, phys_addr_t *phys_addr) ++{ ++ int i; ++ struct device *root_dprc_dev; ++ struct fsl_mc *mc; ++ ++ fsl_mc_get_root_dprc(&mc_dev->dev, &root_dprc_dev); ++ mc = dev_get_drvdata(root_dprc_dev->parent); ++ ++ if (mc->num_translation_ranges == 0) { ++ /* ++ * Do identity mapping: ++ */ ++ *phys_addr = mc_offset; ++ return 0; ++ } ++ ++ for (i = 0; i < mc->num_translation_ranges; i++) { ++ struct fsl_mc_addr_translation_range *range = ++ &mc->translation_ranges[i]; ++ ++ if (mc_region_type == range->mc_region_type && ++ mc_offset >= range->start_mc_offset && ++ mc_offset < range->end_mc_offset) { ++ *phys_addr = range->start_phys_addr + ++ (mc_offset - range->start_mc_offset); ++ return 0; ++ } ++ } ++ ++ return -EFAULT; ++} ++ ++static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev, ++ struct fsl_mc_device *mc_bus_dev) ++{ ++ int i; ++ int error; ++ struct resource *regions; ++ struct fsl_mc_obj_desc *obj_desc = &mc_dev->obj_desc; ++ struct device *parent_dev = mc_dev->dev.parent; ++ enum dprc_region_type mc_region_type; ++ ++ if (is_fsl_mc_bus_dprc(mc_dev) || ++ is_fsl_mc_bus_dpmcp(mc_dev)) { ++ mc_region_type = DPRC_REGION_TYPE_MC_PORTAL; ++ } else if (is_fsl_mc_bus_dpio(mc_dev)) { ++ mc_region_type = DPRC_REGION_TYPE_QBMAN_PORTAL; ++ } else { ++ /* ++ * This function should not have been called for this MC object ++ * type, as this object type is not supposed to have MMIO ++ * regions ++ */ ++ return -EINVAL; ++ } ++ ++ regions = kmalloc_array(obj_desc->region_count, ++ sizeof(regions[0]), GFP_KERNEL); ++ if (!regions) ++ return -ENOMEM; ++ ++ for (i = 0; i < obj_desc->region_count; i++) { ++ struct dprc_region_desc region_desc; ++ ++ error = dprc_get_obj_region(mc_bus_dev->mc_io, ++ 0, ++ mc_bus_dev->mc_handle, ++ obj_desc->type, ++ obj_desc->id, i, ®ion_desc); ++ if (error < 0) { ++ dev_err(parent_dev, ++ "dprc_get_obj_region() failed: %d\n", error); ++ goto error_cleanup_regions; ++ } ++ ++ error = translate_mc_addr(mc_dev, mc_region_type, ++ region_desc.base_offset, ++ ®ions[i].start); ++ if (error < 0) { ++ dev_err(parent_dev, ++ "Invalid MC offset: %#x (for %s.%d\'s region %d)\n", ++ region_desc.base_offset, ++ obj_desc->type, obj_desc->id, i); ++ goto error_cleanup_regions; ++ } ++ ++ regions[i].end = regions[i].start + region_desc.size - 1; ++ regions[i].name = "fsl-mc object MMIO region"; ++ regions[i].flags = IORESOURCE_IO; ++ if (region_desc.flags & DPRC_REGION_CACHEABLE) ++ regions[i].flags |= IORESOURCE_CACHEABLE; ++ } ++ ++ mc_dev->regions = regions; ++ return 0; ++ ++error_cleanup_regions: ++ kfree(regions); ++ return error; ++} ++ ++/** ++ * fsl_mc_is_root_dprc - function to check if a given device is a root dprc ++ */ ++bool fsl_mc_is_root_dprc(struct device *dev) ++{ ++ struct device *root_dprc_dev; ++ ++ fsl_mc_get_root_dprc(dev, &root_dprc_dev); ++ if (!root_dprc_dev) ++ return false; ++ return dev == root_dprc_dev; ++} ++ ++static void fsl_mc_device_release(struct device *dev) ++{ ++ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); ++ ++ kfree(mc_dev->regions); ++ ++ if (is_fsl_mc_bus_dprc(mc_dev)) ++ kfree(to_fsl_mc_bus(mc_dev)); ++ else ++ kfree(mc_dev); ++} ++ ++/** ++ * Add a newly discovered fsl-mc device to be visible in Linux ++ */ ++int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc, ++ struct fsl_mc_io *mc_io, ++ struct device *parent_dev, ++ const char *driver_override, ++ struct fsl_mc_device **new_mc_dev) ++{ ++ int error; ++ struct fsl_mc_device *mc_dev = NULL; ++ struct fsl_mc_bus *mc_bus = NULL; ++ struct fsl_mc_device *parent_mc_dev; ++ struct device *fsl_mc_platform_dev; ++ struct device_node *fsl_mc_platform_node; ++ ++ if (dev_is_fsl_mc(parent_dev)) ++ parent_mc_dev = to_fsl_mc_device(parent_dev); ++ else ++ parent_mc_dev = NULL; ++ ++ if (strcmp(obj_desc->type, "dprc") == 0) { ++ /* ++ * Allocate an MC bus device object: ++ */ ++ mc_bus = kzalloc(sizeof(*mc_bus), GFP_KERNEL); ++ if (!mc_bus) ++ return -ENOMEM; ++ ++ mc_dev = &mc_bus->mc_dev; ++ } else { ++ /* ++ * Allocate a regular fsl_mc_device object: ++ */ ++ mc_dev = kzalloc(sizeof(*mc_dev), GFP_KERNEL); ++ if (!mc_dev) ++ return -ENOMEM; ++ } ++ ++ mc_dev->obj_desc = *obj_desc; ++ mc_dev->mc_io = mc_io; ++ ++ if (driver_override) { ++ /* ++ * We trust driver_override, so we don't need to use ++ * kstrndup() here ++ */ ++ mc_dev->driver_override = kstrdup(driver_override, GFP_KERNEL); ++ if (!mc_dev->driver_override) { ++ error = -ENOMEM; ++ goto error_cleanup_dev; ++ } ++ } ++ ++ device_initialize(&mc_dev->dev); ++ mc_dev->dev.parent = parent_dev; ++ mc_dev->dev.bus = &fsl_mc_bus_type; ++ mc_dev->dev.release = fsl_mc_device_release; ++ mc_dev->dev.type = fsl_mc_get_device_type(obj_desc->type); ++ if (!mc_dev->dev.type) { ++ error = -ENODEV; ++ dev_err(parent_dev, "unknown device type %s\n", obj_desc->type); ++ goto error_cleanup_dev; ++ } ++ dev_set_name(&mc_dev->dev, "%s.%d", obj_desc->type, obj_desc->id); ++ ++ if (strcmp(obj_desc->type, "dprc") == 0) { ++ struct fsl_mc_io *mc_io2; ++ ++ mc_dev->flags |= FSL_MC_IS_DPRC; ++ ++ /* ++ * To get the DPRC's ICID, we need to open the DPRC ++ * in get_dprc_icid(). For child DPRCs, we do so using the ++ * parent DPRC's MC portal instead of the child DPRC's MC ++ * portal, in case the child DPRC is already opened with ++ * its own portal (e.g., the DPRC used by AIOP). ++ * ++ * NOTE: There cannot be more than one active open for a ++ * given MC object, using the same MC portal. ++ */ ++ if (parent_mc_dev) { ++ /* ++ * device being added is a child DPRC device ++ */ ++ mc_io2 = parent_mc_dev->mc_io; ++ } else { ++ /* ++ * device being added is the root DPRC device ++ */ ++ if (!mc_io) { ++ error = -EINVAL; ++ goto error_cleanup_dev; ++ } ++ ++ mc_io2 = mc_io; ++ } ++ ++ error = get_dprc_icid(mc_io2, obj_desc->id, &mc_dev->icid); ++ if (error < 0) ++ goto error_cleanup_dev; ++ } else { ++ /* ++ * A non-DPRC object has to be a child of a DPRC, use the ++ * parent's ICID and interrupt domain. ++ */ ++ mc_dev->icid = parent_mc_dev->icid; ++ mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK; ++ mc_dev->dev.dma_mask = &mc_dev->dma_mask; ++ mc_dev->dev.coherent_dma_mask = mc_dev->dma_mask; ++ dev_set_msi_domain(&mc_dev->dev, ++ dev_get_msi_domain(&parent_mc_dev->dev)); ++ } ++ ++ /* ++ * Get MMIO regions for the device from the MC: ++ * ++ * NOTE: the root DPRC is a special case as its MMIO region is ++ * obtained from the device tree ++ */ ++ if (parent_mc_dev && obj_desc->region_count != 0) { ++ error = fsl_mc_device_get_mmio_regions(mc_dev, ++ parent_mc_dev); ++ if (error < 0) ++ goto error_cleanup_dev; ++ } ++ ++ fsl_mc_platform_dev = &mc_dev->dev; ++ while (dev_is_fsl_mc(fsl_mc_platform_dev)) ++ fsl_mc_platform_dev = fsl_mc_platform_dev->parent; ++ fsl_mc_platform_node = fsl_mc_platform_dev->of_node; ++ ++ /* Set up the iommu configuration for the devices. */ ++ fsl_mc_dma_configure(mc_dev, fsl_mc_platform_node, ++ !(obj_desc->flags & DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY)); ++ ++ /* ++ * The device-specific probe callback will get invoked by device_add() ++ */ ++ error = device_add(&mc_dev->dev); ++ if (error < 0) { ++ dev_err(parent_dev, ++ "device_add() failed for device %s: %d\n", ++ dev_name(&mc_dev->dev), error); ++ goto error_cleanup_dev; ++ } ++ ++ dev_dbg(parent_dev, "added %s\n", dev_name(&mc_dev->dev)); ++ ++ *new_mc_dev = mc_dev; ++ return 0; ++ ++error_cleanup_dev: ++ kfree(mc_dev->regions); ++ kfree(mc_bus); ++ kfree(mc_dev); ++ ++ return error; ++} ++EXPORT_SYMBOL_GPL(fsl_mc_device_add); ++ ++/** ++ * fsl_mc_device_remove - Remove an fsl-mc device from being visible to ++ * Linux ++ * ++ * @mc_dev: Pointer to an fsl-mc device ++ */ ++void fsl_mc_device_remove(struct fsl_mc_device *mc_dev) ++{ ++ kfree(mc_dev->driver_override); ++ mc_dev->driver_override = NULL; ++ ++ /* ++ * The device-specific remove callback will get invoked by device_del() ++ */ ++ device_del(&mc_dev->dev); ++ put_device(&mc_dev->dev); ++} ++EXPORT_SYMBOL_GPL(fsl_mc_device_remove); ++ ++static int parse_mc_ranges(struct device *dev, ++ int *paddr_cells, ++ int *mc_addr_cells, ++ int *mc_size_cells, ++ const __be32 **ranges_start) ++{ ++ const __be32 *prop; ++ int range_tuple_cell_count; ++ int ranges_len; ++ int tuple_len; ++ struct device_node *mc_node = dev->of_node; ++ ++ *ranges_start = of_get_property(mc_node, "ranges", &ranges_len); ++ if (!(*ranges_start) || !ranges_len) { ++ dev_warn(dev, ++ "missing or empty ranges property for device tree node '%s'\n", ++ mc_node->name); ++ return 0; ++ } ++ ++ *paddr_cells = of_n_addr_cells(mc_node); ++ ++ prop = of_get_property(mc_node, "#address-cells", NULL); ++ if (prop) ++ *mc_addr_cells = be32_to_cpup(prop); ++ else ++ *mc_addr_cells = *paddr_cells; ++ ++ prop = of_get_property(mc_node, "#size-cells", NULL); ++ if (prop) ++ *mc_size_cells = be32_to_cpup(prop); ++ else ++ *mc_size_cells = of_n_size_cells(mc_node); ++ ++ range_tuple_cell_count = *paddr_cells + *mc_addr_cells + ++ *mc_size_cells; ++ ++ tuple_len = range_tuple_cell_count * sizeof(__be32); ++ if (ranges_len % tuple_len != 0) { ++ dev_err(dev, "malformed ranges property '%s'\n", mc_node->name); ++ return -EINVAL; ++ } ++ ++ return ranges_len / tuple_len; ++} ++ ++static int get_mc_addr_translation_ranges(struct device *dev, ++ struct fsl_mc_addr_translation_range ++ **ranges, ++ u8 *num_ranges) ++{ ++ int ret; ++ int paddr_cells; ++ int mc_addr_cells; ++ int mc_size_cells; ++ int i; ++ const __be32 *ranges_start; ++ const __be32 *cell; ++ ++ ret = parse_mc_ranges(dev, ++ &paddr_cells, ++ &mc_addr_cells, ++ &mc_size_cells, ++ &ranges_start); ++ if (ret < 0) ++ return ret; ++ ++ *num_ranges = ret; ++ if (!ret) { ++ /* ++ * Missing or empty ranges property ("ranges;") for the ++ * 'fsl,qoriq-mc' node. In this case, identity mapping ++ * will be used. ++ */ ++ *ranges = NULL; ++ return 0; ++ } ++ ++ *ranges = devm_kcalloc(dev, *num_ranges, ++ sizeof(struct fsl_mc_addr_translation_range), ++ GFP_KERNEL); ++ if (!(*ranges)) ++ return -ENOMEM; ++ ++ cell = ranges_start; ++ for (i = 0; i < *num_ranges; ++i) { ++ struct fsl_mc_addr_translation_range *range = &(*ranges)[i]; ++ ++ range->mc_region_type = of_read_number(cell, 1); ++ range->start_mc_offset = of_read_number(cell + 1, ++ mc_addr_cells - 1); ++ cell += mc_addr_cells; ++ range->start_phys_addr = of_read_number(cell, paddr_cells); ++ cell += paddr_cells; ++ range->end_mc_offset = range->start_mc_offset + ++ of_read_number(cell, mc_size_cells); ++ ++ cell += mc_size_cells; ++ } ++ ++ return 0; ++} ++ ++/** ++ * fsl_mc_bus_probe - callback invoked when the root MC bus is being ++ * added ++ */ ++static int fsl_mc_bus_probe(struct platform_device *pdev) ++{ ++ struct fsl_mc_obj_desc obj_desc; ++ int error; ++ struct fsl_mc *mc; ++ struct fsl_mc_device *mc_bus_dev = NULL; ++ struct fsl_mc_io *mc_io = NULL; ++ struct fsl_mc_bus *mc_bus = NULL; ++ int container_id; ++ phys_addr_t mc_portal_phys_addr; ++ u32 mc_portal_size; ++ struct mc_version mc_version; ++ struct resource res; ++ ++ mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL); ++ if (!mc) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, mc); ++ ++ /* ++ * Get physical address of MC portal for the root DPRC: ++ */ ++ error = of_address_to_resource(pdev->dev.of_node, 0, &res); ++ if (error < 0) { ++ dev_err(&pdev->dev, ++ "of_address_to_resource() failed for %pOF\n", ++ pdev->dev.of_node); ++ return error; ++ } ++ ++ mc_portal_phys_addr = res.start; ++ mc_portal_size = resource_size(&res); ++ error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr, ++ mc_portal_size, NULL, ++ FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, &mc_io); ++ if (error < 0) ++ return error; ++ ++ error = mc_get_version(mc_io, 0, &mc_version); ++ if (error != 0) { ++ dev_err(&pdev->dev, ++ "mc_get_version() failed with error %d\n", error); ++ goto error_cleanup_mc_io; ++ } ++ ++ dev_info(&pdev->dev, "MC firmware version: %u.%u.%u\n", ++ mc_version.major, mc_version.minor, mc_version.revision); ++ ++ error = get_mc_addr_translation_ranges(&pdev->dev, ++ &mc->translation_ranges, ++ &mc->num_translation_ranges); ++ if (error < 0) ++ goto error_cleanup_mc_io; ++ ++ error = dprc_get_container_id(mc_io, 0, &container_id); ++ if (error < 0) { ++ dev_err(&pdev->dev, ++ "dprc_get_container_id() failed: %d\n", error); ++ goto error_cleanup_mc_io; ++ } ++ ++ memset(&obj_desc, 0, sizeof(struct fsl_mc_obj_desc)); ++ error = dprc_get_api_version(mc_io, 0, ++ &obj_desc.ver_major, ++ &obj_desc.ver_minor); ++ if (error < 0) ++ goto error_cleanup_mc_io; ++ ++ obj_desc.vendor = FSL_MC_VENDOR_FREESCALE; ++ strcpy(obj_desc.type, "dprc"); ++ obj_desc.id = container_id; ++ obj_desc.irq_count = 1; ++ obj_desc.region_count = 0; ++ ++ error = fsl_mc_device_add(&obj_desc, mc_io, &pdev->dev, NULL, ++ &mc_bus_dev); ++ if (error < 0) ++ goto error_cleanup_mc_io; ++ ++ mc_bus = to_fsl_mc_bus(mc_bus_dev); ++ error = fsl_mc_restool_create_device_file(mc_bus); ++ if (error < 0) ++ goto error_cleanup_device; ++ ++ mc->root_mc_bus_dev = mc_bus_dev; ++ ++ return 0; ++ ++error_cleanup_device: ++ fsl_mc_device_remove(mc_bus_dev); ++ ++error_cleanup_mc_io: ++ fsl_destroy_mc_io(mc_io); ++ return error; ++} ++ ++/** ++ * fsl_mc_bus_remove - callback invoked when the root MC bus is being ++ * removed ++ */ ++static int fsl_mc_bus_remove(struct platform_device *pdev) ++{ ++ struct fsl_mc *mc = platform_get_drvdata(pdev); ++ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc->root_mc_bus_dev); ++ ++ if (!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev)) ++ return -EINVAL; ++ ++ fsl_mc_restool_remove_device_file(mc_bus); ++ fsl_mc_device_remove(mc->root_mc_bus_dev); ++ ++ fsl_destroy_mc_io(mc->root_mc_bus_dev->mc_io); ++ mc->root_mc_bus_dev->mc_io = NULL; ++ ++ return 0; ++} ++ ++static const struct of_device_id fsl_mc_bus_match_table[] = { ++ {.compatible = "fsl,qoriq-mc",}, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, fsl_mc_bus_match_table); ++ ++static struct platform_driver fsl_mc_bus_driver = { ++ .driver = { ++ .name = "fsl_mc_bus", ++ .pm = NULL, ++ .of_match_table = fsl_mc_bus_match_table, ++ }, ++ .probe = fsl_mc_bus_probe, ++ .remove = fsl_mc_bus_remove, ++}; ++ ++static int __init fsl_mc_bus_driver_init(void) ++{ ++ int error; ++ ++ error = bus_register(&fsl_mc_bus_type); ++ if (error < 0) { ++ pr_err("bus type registration failed: %d\n", error); ++ goto error_cleanup_cache; ++ } ++ ++ error = platform_driver_register(&fsl_mc_bus_driver); ++ if (error < 0) { ++ pr_err("platform_driver_register() failed: %d\n", error); ++ goto error_cleanup_bus; ++ } ++ ++ error = dprc_driver_init(); ++ if (error < 0) ++ goto error_cleanup_driver; ++ ++ error = fsl_mc_allocator_driver_init(); ++ if (error < 0) ++ goto error_cleanup_dprc_driver; ++ ++ error = fsl_mc_restool_init(); ++ if (error < 0) ++ goto error_cleanup_mc_allocator; ++ ++ return 0; ++ ++error_cleanup_mc_allocator: ++ fsl_mc_allocator_driver_exit(); ++ ++error_cleanup_dprc_driver: ++ dprc_driver_exit(); ++ ++error_cleanup_driver: ++ platform_driver_unregister(&fsl_mc_bus_driver); ++ ++error_cleanup_bus: ++ bus_unregister(&fsl_mc_bus_type); ++ ++error_cleanup_cache: ++ return error; ++} ++postcore_initcall(fsl_mc_bus_driver_init); +--- /dev/null ++++ b/drivers/bus/fsl-mc/fsl-mc-iommu.c +@@ -0,0 +1,78 @@ ++/* ++ * Copyright 2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ * Author: Nipun Gupta <nipun.gupta@nxp.com> ++ * ++ * 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 <linux/iommu.h> ++#include <linux/of.h> ++#include <linux/of_iommu.h> ++#include <linux/fsl/mc.h> ++ ++/* Setup the IOMMU for the DPRC container */ ++static const struct iommu_ops ++*fsl_mc_iommu_configure(struct fsl_mc_device *mc_dev, ++ struct device_node *fsl_mc_platform_node) ++{ ++ struct of_phandle_args iommu_spec; ++ const struct iommu_ops *ops; ++ u32 iommu_phandle; ++ struct device_node *iommu_node; ++ const __be32 *map = NULL; ++ int iommu_cells, map_len, ret; ++ ++ map = of_get_property(fsl_mc_platform_node, "iommu-map", &map_len); ++ if (!map) ++ return NULL; ++ ++ ops = mc_dev->dev.bus->iommu_ops; ++ if (!ops || !ops->of_xlate) ++ return NULL; ++ ++ iommu_phandle = be32_to_cpup(map + 1); ++ iommu_node = of_find_node_by_phandle(iommu_phandle); ++ ++ if (of_property_read_u32(iommu_node, "#iommu-cells", &iommu_cells)) { ++ pr_err("%s: missing #iommu-cells property\n", iommu_node->name); ++ return NULL; ++ } ++ ++ /* Initialize the fwspec */ ++ ret = iommu_fwspec_init(&mc_dev->dev, &iommu_node->fwnode, ops); ++ if (ret) ++ return NULL; ++ ++ /* ++ * Fill in the required stream-id before calling the iommu's ++ * ops->xlate callback. ++ */ ++ iommu_spec.np = iommu_node; ++ iommu_spec.args[0] = mc_dev->icid; ++ iommu_spec.args_count = 1; ++ ++ ret = ops->of_xlate(&mc_dev->dev, &iommu_spec); ++ if (ret) ++ return NULL; ++ ++ of_node_put(iommu_spec.np); ++ ++ return ops; ++} ++ ++/* Set up DMA configuration for fsl-mc devices */ ++void fsl_mc_dma_configure(struct fsl_mc_device *mc_dev, ++ struct device_node *fsl_mc_platform_node, int coherent) ++{ ++ const struct iommu_ops *ops; ++ ++ ops = fsl_mc_iommu_configure(mc_dev, fsl_mc_platform_node); ++ ++ mc_dev->dev.coherent_dma_mask = DMA_BIT_MASK(48); ++ mc_dev->dev.dma_mask = &mc_dev->dev.coherent_dma_mask; ++ arch_setup_dma_ops(&mc_dev->dev, 0, ++ mc_dev->dev.coherent_dma_mask + 1, ops, coherent); ++} +--- a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c ++++ /dev/null +@@ -1,285 +0,0 @@ +-/* +- * Freescale Management Complex (MC) bus driver MSI support +- * +- * Copyright (C) 2015 Freescale Semiconductor, Inc. +- * Author: German Rivera <German.Rivera@freescale.com> +- * +- * 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 <linux/of_device.h> +-#include <linux/of_address.h> +-#include <linux/irqchip/arm-gic-v3.h> +-#include <linux/of_irq.h> +-#include <linux/irq.h> +-#include <linux/irqdomain.h> +-#include <linux/msi.h> +-#include "../include/mc-bus.h" +-#include "fsl-mc-private.h" +- +-/* +- * Generate a unique ID identifying the interrupt (only used within the MSI +- * irqdomain. Combine the icid with the interrupt index. +- */ +-static irq_hw_number_t fsl_mc_domain_calc_hwirq(struct fsl_mc_device *dev, +- struct msi_desc *desc) +-{ +- /* +- * Make the base hwirq value for ICID*10000 so it is readable +- * as a decimal value in /proc/interrupts. +- */ +- return (irq_hw_number_t)(desc->fsl_mc.msi_index + (dev->icid * 10000)); +-} +- +-static void fsl_mc_msi_set_desc(msi_alloc_info_t *arg, +- struct msi_desc *desc) +-{ +- arg->desc = desc; +- arg->hwirq = fsl_mc_domain_calc_hwirq(to_fsl_mc_device(desc->dev), +- desc); +-} +- +-static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info) +-{ +- struct msi_domain_ops *ops = info->ops; +- +- if (WARN_ON(!ops)) +- return; +- +- /* +- * set_desc should not be set by the caller +- */ +- if (!ops->set_desc) +- ops->set_desc = fsl_mc_msi_set_desc; +-} +- +-static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev, +- struct fsl_mc_device_irq *mc_dev_irq) +-{ +- int error; +- struct fsl_mc_device *owner_mc_dev = mc_dev_irq->mc_dev; +- struct msi_desc *msi_desc = mc_dev_irq->msi_desc; +- struct dprc_irq_cfg irq_cfg; +- +- /* +- * msi_desc->msg.address is 0x0 when this function is invoked in +- * the free_irq() code path. In this case, for the MC, we don't +- * really need to "unprogram" the MSI, so we just return. +- */ +- if (msi_desc->msg.address_lo == 0x0 && msi_desc->msg.address_hi == 0x0) +- return; +- +- if (WARN_ON(!owner_mc_dev)) +- return; +- +- irq_cfg.paddr = ((u64)msi_desc->msg.address_hi << 32) | +- msi_desc->msg.address_lo; +- irq_cfg.val = msi_desc->msg.data; +- irq_cfg.irq_num = msi_desc->irq; +- +- if (owner_mc_dev == mc_bus_dev) { +- /* +- * IRQ is for the mc_bus_dev's DPRC itself +- */ +- error = dprc_set_irq(mc_bus_dev->mc_io, +- MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI, +- mc_bus_dev->mc_handle, +- mc_dev_irq->dev_irq_index, +- &irq_cfg); +- if (error < 0) { +- dev_err(&owner_mc_dev->dev, +- "dprc_set_irq() failed: %d\n", error); +- } +- } else { +- /* +- * IRQ is for for a child device of mc_bus_dev +- */ +- error = dprc_set_obj_irq(mc_bus_dev->mc_io, +- MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI, +- mc_bus_dev->mc_handle, +- owner_mc_dev->obj_desc.type, +- owner_mc_dev->obj_desc.id, +- mc_dev_irq->dev_irq_index, +- &irq_cfg); +- if (error < 0) { +- dev_err(&owner_mc_dev->dev, +- "dprc_obj_set_irq() failed: %d\n", error); +- } +- } +-} +- +-/* +- * NOTE: This function is invoked with interrupts disabled +- */ +-static void fsl_mc_msi_write_msg(struct irq_data *irq_data, +- struct msi_msg *msg) +-{ +- struct msi_desc *msi_desc = irq_data_get_msi_desc(irq_data); +- struct fsl_mc_device *mc_bus_dev = to_fsl_mc_device(msi_desc->dev); +- struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); +- struct fsl_mc_device_irq *mc_dev_irq = +- &mc_bus->irq_resources[msi_desc->fsl_mc.msi_index]; +- +- WARN_ON(mc_dev_irq->msi_desc != msi_desc); +- msi_desc->msg = *msg; +- +- /* +- * Program the MSI (paddr, value) pair in the device: +- */ +- __fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq); +-} +- +-static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info) +-{ +- struct irq_chip *chip = info->chip; +- +- if (WARN_ON((!chip))) +- return; +- +- /* +- * irq_write_msi_msg should not be set by the caller +- */ +- if (!chip->irq_write_msi_msg) +- chip->irq_write_msi_msg = fsl_mc_msi_write_msg; +-} +- +-/** +- * fsl_mc_msi_create_irq_domain - Create a fsl-mc MSI interrupt domain +- * @np: Optional device-tree node of the interrupt controller +- * @info: MSI domain info +- * @parent: Parent irq domain +- * +- * Updates the domain and chip ops and creates a fsl-mc MSI +- * interrupt domain. +- * +- * Returns: +- * A domain pointer or NULL in case of failure. +- */ +-struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, +- struct msi_domain_info *info, +- struct irq_domain *parent) +-{ +- struct irq_domain *domain; +- +- if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS) +- fsl_mc_msi_update_dom_ops(info); +- if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) +- fsl_mc_msi_update_chip_ops(info); +- +- domain = msi_create_irq_domain(fwnode, info, parent); +- if (domain) +- domain->bus_token = DOMAIN_BUS_FSL_MC_MSI; +- +- return domain; +-} +- +-int fsl_mc_find_msi_domain(struct device *mc_platform_dev, +- struct irq_domain **mc_msi_domain) +-{ +- struct irq_domain *msi_domain; +- struct device_node *mc_of_node = mc_platform_dev->of_node; +- +- msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node, +- DOMAIN_BUS_FSL_MC_MSI); +- if (!msi_domain) { +- pr_err("Unable to find fsl-mc MSI domain for %s\n", +- mc_of_node->full_name); +- +- return -ENOENT; +- } +- +- *mc_msi_domain = msi_domain; +- return 0; +-} +- +-static void fsl_mc_msi_free_descs(struct device *dev) +-{ +- struct msi_desc *desc, *tmp; +- +- list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) { +- list_del(&desc->list); +- free_msi_entry(desc); +- } +-} +- +-static int fsl_mc_msi_alloc_descs(struct device *dev, unsigned int irq_count) +- +-{ +- unsigned int i; +- int error; +- struct msi_desc *msi_desc; +- +- for (i = 0; i < irq_count; i++) { +- msi_desc = alloc_msi_entry(dev, 1, NULL); +- if (!msi_desc) { +- dev_err(dev, "Failed to allocate msi entry\n"); +- error = -ENOMEM; +- goto cleanup_msi_descs; +- } +- +- msi_desc->fsl_mc.msi_index = i; +- INIT_LIST_HEAD(&msi_desc->list); +- list_add_tail(&msi_desc->list, dev_to_msi_list(dev)); +- } +- +- return 0; +- +-cleanup_msi_descs: +- fsl_mc_msi_free_descs(dev); +- return error; +-} +- +-int fsl_mc_msi_domain_alloc_irqs(struct device *dev, +- unsigned int irq_count) +-{ +- struct irq_domain *msi_domain; +- int error; +- +- if (WARN_ON(!list_empty(dev_to_msi_list(dev)))) +- return -EINVAL; +- +- error = fsl_mc_msi_alloc_descs(dev, irq_count); +- if (error < 0) +- return error; +- +- msi_domain = dev_get_msi_domain(dev); +- if (WARN_ON(!msi_domain)) { +- error = -EINVAL; +- goto cleanup_msi_descs; +- } +- +- /* +- * NOTE: Calling this function will trigger the invocation of the +- * its_fsl_mc_msi_prepare() callback +- */ +- error = msi_domain_alloc_irqs(msi_domain, dev, irq_count); +- +- if (error) { +- dev_err(dev, "Failed to allocate IRQs\n"); +- goto cleanup_msi_descs; +- } +- +- return 0; +- +-cleanup_msi_descs: +- fsl_mc_msi_free_descs(dev); +- return error; +-} +- +-void fsl_mc_msi_domain_free_irqs(struct device *dev) +-{ +- struct irq_domain *msi_domain; +- +- msi_domain = dev_get_msi_domain(dev); +- if (WARN_ON(!msi_domain)) +- return; +- +- msi_domain_free_irqs(msi_domain, dev); +- +- if (WARN_ON(list_empty(dev_to_msi_list(dev)))) +- return; +- +- fsl_mc_msi_free_descs(dev); +-} +--- /dev/null ++++ b/drivers/bus/fsl-mc/fsl-mc-msi.c +@@ -0,0 +1,285 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Freescale Management Complex (MC) bus driver MSI support ++ * ++ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. ++ * Author: German Rivera <German.Rivera@freescale.com> ++ * ++ */ ++ ++#include <linux/of_device.h> ++#include <linux/of_address.h> ++#include <linux/of_irq.h> ++#include <linux/irq.h> ++#include <linux/irqdomain.h> ++#include <linux/msi.h> ++ ++#include "fsl-mc-private.h" ++ ++#ifdef GENERIC_MSI_DOMAIN_OPS ++/* ++ * Generate a unique ID identifying the interrupt (only used within the MSI ++ * irqdomain. Combine the icid with the interrupt index. ++ */ ++static irq_hw_number_t fsl_mc_domain_calc_hwirq(struct fsl_mc_device *dev, ++ struct msi_desc *desc) ++{ ++ /* ++ * Make the base hwirq value for ICID*10000 so it is readable ++ * as a decimal value in /proc/interrupts. ++ */ ++ return (irq_hw_number_t)(desc->fsl_mc.msi_index + (dev->icid * 10000)); ++} ++ ++static void fsl_mc_msi_set_desc(msi_alloc_info_t *arg, ++ struct msi_desc *desc) ++{ ++ arg->desc = desc; ++ arg->hwirq = fsl_mc_domain_calc_hwirq(to_fsl_mc_device(desc->dev), ++ desc); ++} ++#else ++#define fsl_mc_msi_set_desc NULL ++#endif ++ ++static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info) ++{ ++ struct msi_domain_ops *ops = info->ops; ++ ++ if (!ops) ++ return; ++ ++ /* ++ * set_desc should not be set by the caller ++ */ ++ if (!ops->set_desc) ++ ops->set_desc = fsl_mc_msi_set_desc; ++} ++ ++static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev, ++ struct fsl_mc_device_irq *mc_dev_irq) ++{ ++ int error; ++ struct fsl_mc_device *owner_mc_dev = mc_dev_irq->mc_dev; ++ struct msi_desc *msi_desc = mc_dev_irq->msi_desc; ++ struct dprc_irq_cfg irq_cfg; ++ ++ /* ++ * msi_desc->msg.address is 0x0 when this function is invoked in ++ * the free_irq() code path. In this case, for the MC, we don't ++ * really need to "unprogram" the MSI, so we just return. ++ */ ++ if (msi_desc->msg.address_lo == 0x0 && msi_desc->msg.address_hi == 0x0) ++ return; ++ ++ if (!owner_mc_dev) ++ return; ++ ++ irq_cfg.paddr = ((u64)msi_desc->msg.address_hi << 32) | ++ msi_desc->msg.address_lo; ++ irq_cfg.val = msi_desc->msg.data; ++ irq_cfg.irq_num = msi_desc->irq; ++ ++ if (owner_mc_dev == mc_bus_dev) { ++ /* ++ * IRQ is for the mc_bus_dev's DPRC itself ++ */ ++ error = dprc_set_irq(mc_bus_dev->mc_io, ++ MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI, ++ mc_bus_dev->mc_handle, ++ mc_dev_irq->dev_irq_index, ++ &irq_cfg); ++ if (error < 0) { ++ dev_err(&owner_mc_dev->dev, ++ "dprc_set_irq() failed: %d\n", error); ++ } ++ } else { ++ /* ++ * IRQ is for for a child device of mc_bus_dev ++ */ ++ error = dprc_set_obj_irq(mc_bus_dev->mc_io, ++ MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI, ++ mc_bus_dev->mc_handle, ++ owner_mc_dev->obj_desc.type, ++ owner_mc_dev->obj_desc.id, ++ mc_dev_irq->dev_irq_index, ++ &irq_cfg); ++ if (error < 0) { ++ dev_err(&owner_mc_dev->dev, ++ "dprc_obj_set_irq() failed: %d\n", error); ++ } ++ } ++} ++ ++/* ++ * NOTE: This function is invoked with interrupts disabled ++ */ ++static void fsl_mc_msi_write_msg(struct irq_data *irq_data, ++ struct msi_msg *msg) ++{ ++ struct msi_desc *msi_desc = irq_data_get_msi_desc(irq_data); ++ struct fsl_mc_device *mc_bus_dev = to_fsl_mc_device(msi_desc->dev); ++ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); ++ struct fsl_mc_device_irq *mc_dev_irq = ++ &mc_bus->irq_resources[msi_desc->fsl_mc.msi_index]; ++ ++ msi_desc->msg = *msg; ++ ++ /* ++ * Program the MSI (paddr, value) pair in the device: ++ */ ++ __fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq); ++} ++ ++static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info) ++{ ++ struct irq_chip *chip = info->chip; ++ ++ if (!chip) ++ return; ++ ++ /* ++ * irq_write_msi_msg should not be set by the caller ++ */ ++ if (!chip->irq_write_msi_msg) ++ chip->irq_write_msi_msg = fsl_mc_msi_write_msg; ++} ++ ++/** ++ * fsl_mc_msi_create_irq_domain - Create a fsl-mc MSI interrupt domain ++ * @np: Optional device-tree node of the interrupt controller ++ * @info: MSI domain info ++ * @parent: Parent irq domain ++ * ++ * Updates the domain and chip ops and creates a fsl-mc MSI ++ * interrupt domain. ++ * ++ * Returns: ++ * A domain pointer or NULL in case of failure. ++ */ ++struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, ++ struct msi_domain_info *info, ++ struct irq_domain *parent) ++{ ++ struct irq_domain *domain; ++ ++ if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS) ++ fsl_mc_msi_update_dom_ops(info); ++ if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) ++ fsl_mc_msi_update_chip_ops(info); ++ ++ domain = msi_create_irq_domain(fwnode, info, parent); ++ if (domain) ++ irq_domain_update_bus_token(domain, DOMAIN_BUS_FSL_MC_MSI); ++ ++ return domain; ++} ++ ++int fsl_mc_find_msi_domain(struct device *mc_platform_dev, ++ struct irq_domain **mc_msi_domain) ++{ ++ struct irq_domain *msi_domain; ++ struct device_node *mc_of_node = mc_platform_dev->of_node; ++ ++ msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node, ++ DOMAIN_BUS_FSL_MC_MSI); ++ if (!msi_domain) { ++ pr_err("Unable to find fsl-mc MSI domain for %pOF\n", ++ mc_of_node); ++ ++ return -ENOENT; ++ } ++ ++ *mc_msi_domain = msi_domain; ++ return 0; ++} ++ ++static void fsl_mc_msi_free_descs(struct device *dev) ++{ ++ struct msi_desc *desc, *tmp; ++ ++ list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) { ++ list_del(&desc->list); ++ free_msi_entry(desc); ++ } ++} ++ ++static int fsl_mc_msi_alloc_descs(struct device *dev, unsigned int irq_count) ++ ++{ ++ unsigned int i; ++ int error; ++ struct msi_desc *msi_desc; ++ ++ for (i = 0; i < irq_count; i++) { ++ msi_desc = alloc_msi_entry(dev, 1, NULL); ++ if (!msi_desc) { ++ dev_err(dev, "Failed to allocate msi entry\n"); ++ error = -ENOMEM; ++ goto cleanup_msi_descs; ++ } ++ ++ msi_desc->fsl_mc.msi_index = i; ++ INIT_LIST_HEAD(&msi_desc->list); ++ list_add_tail(&msi_desc->list, dev_to_msi_list(dev)); ++ } ++ ++ return 0; ++ ++cleanup_msi_descs: ++ fsl_mc_msi_free_descs(dev); ++ return error; ++} ++ ++int fsl_mc_msi_domain_alloc_irqs(struct device *dev, ++ unsigned int irq_count) ++{ ++ struct irq_domain *msi_domain; ++ int error; ++ ++ if (!list_empty(dev_to_msi_list(dev))) ++ return -EINVAL; ++ ++ error = fsl_mc_msi_alloc_descs(dev, irq_count); ++ if (error < 0) ++ return error; ++ ++ msi_domain = dev_get_msi_domain(dev); ++ if (!msi_domain) { ++ error = -EINVAL; ++ goto cleanup_msi_descs; ++ } ++ ++ /* ++ * NOTE: Calling this function will trigger the invocation of the ++ * its_fsl_mc_msi_prepare() callback ++ */ ++ error = msi_domain_alloc_irqs(msi_domain, dev, irq_count); ++ ++ if (error) { ++ dev_err(dev, "Failed to allocate IRQs\n"); ++ goto cleanup_msi_descs; ++ } ++ ++ return 0; ++ ++cleanup_msi_descs: ++ fsl_mc_msi_free_descs(dev); ++ return error; ++} ++ ++void fsl_mc_msi_domain_free_irqs(struct device *dev) ++{ ++ struct irq_domain *msi_domain; ++ ++ msi_domain = dev_get_msi_domain(dev); ++ if (!msi_domain) ++ return; ++ ++ msi_domain_free_irqs(msi_domain, dev); ++ ++ if (list_empty(dev_to_msi_list(dev))) ++ return; ++ ++ fsl_mc_msi_free_descs(dev); ++} +--- /dev/null ++++ b/drivers/bus/fsl-mc/fsl-mc-private.h +@@ -0,0 +1,223 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Freescale Management Complex (MC) bus private declarations ++ * ++ * Copyright (C) 2016 Freescale Semiconductor, Inc. ++ * ++ */ ++#ifndef _FSL_MC_PRIVATE_H_ ++#define _FSL_MC_PRIVATE_H_ ++ ++#include <linux/fsl/mc.h> ++#include <linux/mutex.h> ++#include <linux/cdev.h> ++#include <linux/ioctl.h> ++ ++/* ++ * Data Path Management Complex (DPMNG) General API ++ */ ++ ++/* DPMNG command versioning */ ++#define DPMNG_CMD_BASE_VERSION 1 ++#define DPMNG_CMD_ID_OFFSET 4 ++ ++#define DPMNG_CMD(id) (((id) << DPMNG_CMD_ID_OFFSET) | DPMNG_CMD_BASE_VERSION) ++ ++/* DPMNG command IDs */ ++#define DPMNG_CMDID_GET_VERSION DPMNG_CMD(0x831) ++ ++struct dpmng_rsp_get_version { ++ __le32 revision; ++ __le32 version_major; ++ __le32 version_minor; ++}; ++ ++/* ++ * Data Path Management Command Portal (DPMCP) API ++ */ ++ ++/* Minimal supported DPMCP Version */ ++#define DPMCP_MIN_VER_MAJOR 3 ++#define DPMCP_MIN_VER_MINOR 0 ++ ++/* DPMCP command versioning */ ++#define DPMCP_CMD_BASE_VERSION 1 ++#define DPMCP_CMD_ID_OFFSET 4 ++ ++#define DPMCP_CMD(id) (((id) << DPMCP_CMD_ID_OFFSET) | DPMCP_CMD_BASE_VERSION) ++ ++/* DPMCP command IDs */ ++#define DPMCP_CMDID_CLOSE DPMCP_CMD(0x800) ++#define DPMCP_CMDID_OPEN DPMCP_CMD(0x80b) ++#define DPMCP_CMDID_RESET DPMCP_CMD(0x005) ++ ++struct dpmcp_cmd_open { ++ __le32 dpmcp_id; ++}; ++ ++/* ++ * Initialization and runtime control APIs for DPMCP ++ */ ++int dpmcp_open(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ int dpmcp_id, ++ u16 *token); ++ ++int dpmcp_close(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token); ++ ++int dpmcp_reset(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token); ++ ++/* ++ * Data Path Buffer Pool (DPBP) API + */ -+#ifndef _FSL_DPBP_CMD_H -+#define _FSL_DPBP_CMD_H + +/* DPBP Version */ +#define DPBP_VER_MAJOR 3 @@ -209,33 +7555,23 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#define DPBP_CMD_BASE_VERSION 1 +#define DPBP_CMD_ID_OFFSET 4 + -+#define DPBP_CMD(id) ((id << DPBP_CMD_ID_OFFSET) | DPBP_CMD_BASE_VERSION) ++#define DPBP_CMD(id) (((id) << DPBP_CMD_ID_OFFSET) | DPBP_CMD_BASE_VERSION) + +/* Command IDs */ +#define DPBP_CMDID_CLOSE DPBP_CMD(0x800) +#define DPBP_CMDID_OPEN DPBP_CMD(0x804) -+#define DPBP_CMDID_GET_API_VERSION DPBP_CMD(0xa04) + +#define DPBP_CMDID_ENABLE DPBP_CMD(0x002) +#define DPBP_CMDID_DISABLE DPBP_CMD(0x003) +#define DPBP_CMDID_GET_ATTR DPBP_CMD(0x004) +#define DPBP_CMDID_RESET DPBP_CMD(0x005) -+#define DPBP_CMDID_IS_ENABLED DPBP_CMD(0x006) + +struct dpbp_cmd_open { + __le32 dpbp_id; +}; + -+struct dpbp_cmd_destroy { -+ __le32 object_id; -+}; -+ +#define DPBP_ENABLE 0x1 + -+struct dpbp_rsp_is_enabled { -+ u8 enabled; -+}; -+ +struct dpbp_rsp_get_attributes { + /* response word 0 */ + __le16 pad; @@ -246,38 +7582,2020 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + __le16 version_minor; +}; + -+#endif /* _FSL_DPBP_CMD_H */ ---- a/drivers/staging/fsl-mc/bus/dpbp.c -+++ b/drivers/staging/fsl-mc/bus/dpbp.c -@@ -1,4 +1,5 @@ ++/* ++ * Data Path Concentrator (DPCON) API ++ */ ++ ++/* DPCON Version */ ++#define DPCON_VER_MAJOR 3 ++#define DPCON_VER_MINOR 2 ++ ++/* Command versioning */ ++#define DPCON_CMD_BASE_VERSION 1 ++#define DPCON_CMD_ID_OFFSET 4 ++ ++#define DPCON_CMD(id) (((id) << DPCON_CMD_ID_OFFSET) | DPCON_CMD_BASE_VERSION) ++ ++/* Command IDs */ ++#define DPCON_CMDID_CLOSE DPCON_CMD(0x800) ++#define DPCON_CMDID_OPEN DPCON_CMD(0x808) ++ ++#define DPCON_CMDID_ENABLE DPCON_CMD(0x002) ++#define DPCON_CMDID_DISABLE DPCON_CMD(0x003) ++#define DPCON_CMDID_GET_ATTR DPCON_CMD(0x004) ++#define DPCON_CMDID_RESET DPCON_CMD(0x005) ++ ++#define DPCON_CMDID_SET_NOTIFICATION DPCON_CMD(0x100) ++ ++struct dpcon_cmd_open { ++ __le32 dpcon_id; ++}; ++ ++#define DPCON_ENABLE 1 ++ ++struct dpcon_rsp_get_attr { ++ /* response word 0 */ ++ __le32 id; ++ __le16 qbman_ch_id; ++ u8 num_priorities; ++ u8 pad; ++}; ++ ++struct dpcon_cmd_set_notification { ++ /* cmd word 0 */ ++ __le32 dpio_id; ++ u8 priority; ++ u8 pad[3]; ++ /* cmd word 1 */ ++ __le64 user_ctx; ++}; ++ ++int __must_check fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc, ++ struct fsl_mc_io *mc_io, ++ struct device *parent_dev, ++ const char *driver_override, ++ struct fsl_mc_device **new_mc_dev); ++ ++int __init dprc_driver_init(void); ++ ++void dprc_driver_exit(void); ++ ++int __init fsl_mc_allocator_driver_init(void); ++ ++void fsl_mc_allocator_driver_exit(void); ++ ++int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, ++ enum fsl_mc_pool_type pool_type, ++ struct fsl_mc_resource ++ **new_resource); ++ ++void fsl_mc_resource_free(struct fsl_mc_resource *resource); ++ ++int fsl_mc_msi_domain_alloc_irqs(struct device *dev, ++ unsigned int irq_count); ++ ++void fsl_mc_msi_domain_free_irqs(struct device *dev); ++ ++int __must_check fsl_create_mc_io(struct device *dev, ++ phys_addr_t mc_portal_phys_addr, ++ u32 mc_portal_size, ++ struct fsl_mc_device *dpmcp_dev, ++ u32 flags, struct fsl_mc_io **new_mc_io); ++ ++void fsl_destroy_mc_io(struct fsl_mc_io *mc_io); ++ ++bool fsl_mc_is_root_dprc(struct device *dev); ++ ++#ifdef CONFIG_FSL_MC_RESTOOL ++ ++int fsl_mc_restool_create_device_file(struct fsl_mc_bus *mc_bus); ++ ++void fsl_mc_restool_remove_device_file(struct fsl_mc_bus *mc_bus); ++ ++int fsl_mc_restool_init(void); ++ ++#else ++ ++static inline int fsl_mc_restool_create_device_file(struct fsl_mc_bus *mc_bus) ++{ ++ return 0; ++} ++ ++static inline void fsl_mc_restool_remove_device_file(struct fsl_mc_bus *mc_bus) ++{ ++} ++ ++static inline int fsl_mc_restool_init(void) ++{ ++ return 0; ++} ++ ++#endif ++ ++#endif /* _FSL_MC_PRIVATE_H_ */ +--- /dev/null ++++ b/drivers/bus/fsl-mc/fsl-mc-restool.c +@@ -0,0 +1,219 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Management Complex (MC) restool support ++ * ++ * Copyright 2018 NXP ++ * ++ */ ++ ++#include <linux/slab.h> ++#include <linux/cdev.h> ++#include <linux/fs.h> ++#include <linux/uaccess.h> ++ ++#include "fsl-mc-private.h" ++ ++#define FSL_MC_BUS_MAX_MINORS 1 ++ ++static struct class *fsl_mc_bus_class; ++static int fsl_mc_bus_major; ++ ++static int fsl_mc_restool_send_command(unsigned long arg, ++ struct fsl_mc_io *mc_io) ++{ ++ struct fsl_mc_command mc_cmd; ++ int error; ++ ++ error = copy_from_user(&mc_cmd, (void __user *)arg, sizeof(mc_cmd)); ++ if (error) ++ return -EFAULT; ++ ++ error = mc_send_command(mc_io, &mc_cmd); ++ if (error) ++ return error; ++ ++ error = copy_to_user((void __user *)arg, &mc_cmd, sizeof(mc_cmd)); ++ if (error) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++int fsl_mc_restool_init(void) ++{ ++ dev_t dev; ++ int error; ++ ++ fsl_mc_bus_class = class_create(THIS_MODULE, "fsl_mc_bus"); ++ if (IS_ERR(fsl_mc_bus_class)) { ++ error = PTR_ERR(fsl_mc_bus_class); ++ return error; ++ } ++ ++ error = alloc_chrdev_region(&dev, 0, ++ FSL_MC_BUS_MAX_MINORS, ++ "fsl_mc_bus"); ++ if (error < 0) ++ return error; ++ ++ fsl_mc_bus_major = MAJOR(dev); ++ ++ return 0; ++} ++ ++static int fsl_mc_restool_dev_open(struct inode *inode, struct file *filep) ++{ ++ struct fsl_mc_device *root_mc_device; ++ struct fsl_mc_restool *mc_restool; ++ struct fsl_mc_bus *mc_bus; ++ struct fsl_mc_io *dynamic_mc_io; ++ int error; ++ ++ mc_restool = container_of(inode->i_cdev, struct fsl_mc_restool, cdev); ++ mc_bus = container_of(mc_restool, struct fsl_mc_bus, restool_misc); ++ root_mc_device = &mc_bus->mc_dev; ++ ++ mutex_lock(&mc_restool->mutex); ++ ++ if (!mc_restool->local_instance_in_use) { ++ filep->private_data = root_mc_device->mc_io; ++ mc_restool->local_instance_in_use = true; ++ } else { ++ dynamic_mc_io = kzalloc(sizeof(*dynamic_mc_io), GFP_KERNEL); ++ if (!dynamic_mc_io) { ++ error = -ENOMEM; ++ goto error_alloc_mc_io; ++ } ++ ++ error = fsl_mc_portal_allocate(root_mc_device, 0, ++ &dynamic_mc_io); ++ if (error) { ++ pr_err("Could not allocate MC portal\n"); ++ goto error_portal_allocate; ++ } ++ ++ mc_restool->dynamic_instance_count++; ++ filep->private_data = dynamic_mc_io; ++ } ++ ++ mutex_unlock(&mc_restool->mutex); ++ ++ return 0; ++ ++error_portal_allocate: ++ kfree(dynamic_mc_io); ++ ++error_alloc_mc_io: ++ mutex_unlock(&mc_restool->mutex); ++ ++ return error; ++} ++ ++static int fsl_mc_restool_dev_release(struct inode *inode, struct file *filep) ++{ ++ struct fsl_mc_device *root_mc_device; ++ struct fsl_mc_restool *mc_restool; ++ struct fsl_mc_bus *mc_bus; ++ struct fsl_mc_io *mc_io; ++ ++ mc_restool = container_of(inode->i_cdev, struct fsl_mc_restool, cdev); ++ mc_bus = container_of(mc_restool, struct fsl_mc_bus, restool_misc); ++ root_mc_device = &mc_bus->mc_dev; ++ mc_io = filep->private_data; ++ ++ mutex_lock(&mc_restool->mutex); ++ ++ if (WARN_ON(!mc_restool->local_instance_in_use && ++ mc_restool->dynamic_instance_count == 0)) { ++ mutex_unlock(&mc_restool->mutex); ++ return -EINVAL; ++ } ++ ++ if (filep->private_data == root_mc_device->mc_io) { ++ mc_restool->local_instance_in_use = false; ++ } else { ++ fsl_mc_portal_free(mc_io); ++ kfree(mc_io); ++ mc_restool->dynamic_instance_count--; ++ } ++ ++ filep->private_data = NULL; ++ mutex_unlock(&mc_restool->mutex); ++ ++ return 0; ++} ++ ++static long fsl_mc_restool_dev_ioctl(struct file *file, ++ unsigned int cmd, ++ unsigned long arg) ++{ ++ int error; ++ ++ switch (cmd) { ++ case RESTOOL_SEND_MC_COMMAND: ++ error = fsl_mc_restool_send_command(arg, file->private_data); ++ break; ++ default: ++ pr_err("%s: unexpected ioctl call number\n", __func__); ++ error = -EINVAL; ++ } ++ ++ return error; ++} ++ ++static const struct file_operations fsl_mc_restool_dev_fops = { ++ .owner = THIS_MODULE, ++ .open = fsl_mc_restool_dev_open, ++ .release = fsl_mc_restool_dev_release, ++ .unlocked_ioctl = fsl_mc_restool_dev_ioctl, ++}; ++ ++int fsl_mc_restool_create_device_file(struct fsl_mc_bus *mc_bus) ++{ ++ struct fsl_mc_device *mc_dev = &mc_bus->mc_dev; ++ struct fsl_mc_restool *mc_restool = &mc_bus->restool_misc; ++ int error; ++ ++ mc_restool = &mc_bus->restool_misc; ++ mc_restool->dev = MKDEV(fsl_mc_bus_major, 0); ++ cdev_init(&mc_restool->cdev, &fsl_mc_restool_dev_fops); ++ ++ error = cdev_add(&mc_restool->cdev, ++ mc_restool->dev, ++ FSL_MC_BUS_MAX_MINORS); ++ if (error) ++ return error; ++ ++ mc_restool->device = device_create(fsl_mc_bus_class, ++ NULL, ++ mc_restool->dev, ++ NULL, ++ "%s", ++ dev_name(&mc_dev->dev)); ++ if (IS_ERR(mc_restool->device)) { ++ error = PTR_ERR(mc_restool->device); ++ goto error_device_create; ++ } ++ ++ mutex_init(&mc_restool->mutex); ++ ++ return 0; ++ ++error_device_create: ++ cdev_del(&mc_restool->cdev); ++ ++ return error; ++} ++ ++void fsl_mc_restool_remove_device_file(struct fsl_mc_bus *mc_bus) ++{ ++ struct fsl_mc_restool *mc_restool = &mc_bus->restool_misc; ++ ++ if (WARN_ON(mc_restool->local_instance_in_use)) ++ return; ++ ++ if (WARN_ON(mc_restool->dynamic_instance_count != 0)) ++ return; ++ ++ cdev_del(&mc_restool->cdev); ++} +--- a/drivers/staging/fsl-mc/bus/mc-io.c ++++ /dev/null +@@ -1,320 +0,0 @@ -/* Copyright 2013-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 the above-listed copyright holders nor the +- * names of any contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +- * POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#include <linux/io.h> +-#include "../include/mc-bus.h" +-#include "../include/mc-sys.h" +- +-#include "fsl-mc-private.h" +-#include "dpmcp.h" +-#include "dpmcp-cmd.h" +- +-static int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io, +- struct fsl_mc_device *dpmcp_dev) +-{ +- int error; +- +- if (WARN_ON(!dpmcp_dev)) +- return -EINVAL; +- +- if (WARN_ON(mc_io->dpmcp_dev)) +- return -EINVAL; +- +- if (WARN_ON(dpmcp_dev->mc_io)) +- return -EINVAL; +- +- error = dpmcp_open(mc_io, +- 0, +- dpmcp_dev->obj_desc.id, +- &dpmcp_dev->mc_handle); +- if (error < 0) +- return error; +- +- mc_io->dpmcp_dev = dpmcp_dev; +- dpmcp_dev->mc_io = mc_io; +- return 0; +-} +- +-static void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io) +-{ +- int error; +- struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; +- +- if (WARN_ON(!dpmcp_dev)) +- return; +- +- if (WARN_ON(dpmcp_dev->mc_io != mc_io)) +- return; +- +- error = dpmcp_close(mc_io, +- 0, +- dpmcp_dev->mc_handle); +- if (error < 0) { +- dev_err(&dpmcp_dev->dev, "dpmcp_close() failed: %d\n", +- error); +- } +- +- mc_io->dpmcp_dev = NULL; +- dpmcp_dev->mc_io = NULL; +-} +- +-/** +- * Creates an MC I/O object +- * +- * @dev: device to be associated with the MC I/O object +- * @mc_portal_phys_addr: physical address of the MC portal to use +- * @mc_portal_size: size in bytes of the MC portal +- * @dpmcp-dev: Pointer to the DPMCP object associated with this MC I/O +- * object or NULL if none. +- * @flags: flags for the new MC I/O object +- * @new_mc_io: Area to return pointer to newly created MC I/O object +- * +- * Returns '0' on Success; Error code otherwise. +- */ +-int __must_check fsl_create_mc_io(struct device *dev, +- phys_addr_t mc_portal_phys_addr, +- u32 mc_portal_size, +- struct fsl_mc_device *dpmcp_dev, +- u32 flags, struct fsl_mc_io **new_mc_io) +-{ +- int error; +- struct fsl_mc_io *mc_io; +- void __iomem *mc_portal_virt_addr; +- struct resource *res; +- +- mc_io = devm_kzalloc(dev, sizeof(*mc_io), GFP_KERNEL); +- if (!mc_io) +- return -ENOMEM; +- +- mc_io->dev = dev; +- mc_io->flags = flags; +- mc_io->portal_phys_addr = mc_portal_phys_addr; +- mc_io->portal_size = mc_portal_size; +- if (flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) +- spin_lock_init(&mc_io->spinlock); +- else +- mutex_init(&mc_io->mutex); +- +- res = devm_request_mem_region(dev, +- mc_portal_phys_addr, +- mc_portal_size, +- "mc_portal"); +- if (!res) { +- dev_err(dev, +- "devm_request_mem_region failed for MC portal %#llx\n", +- mc_portal_phys_addr); +- return -EBUSY; +- } +- +- mc_portal_virt_addr = devm_ioremap_nocache(dev, +- mc_portal_phys_addr, +- mc_portal_size); +- if (!mc_portal_virt_addr) { +- dev_err(dev, +- "devm_ioremap_nocache failed for MC portal %#llx\n", +- mc_portal_phys_addr); +- return -ENXIO; +- } +- +- mc_io->portal_virt_addr = mc_portal_virt_addr; +- if (dpmcp_dev) { +- error = fsl_mc_io_set_dpmcp(mc_io, dpmcp_dev); +- if (error < 0) +- goto error_destroy_mc_io; +- } +- +- *new_mc_io = mc_io; +- return 0; +- +-error_destroy_mc_io: +- fsl_destroy_mc_io(mc_io); +- return error; +-} +- +-/** +- * Destroys an MC I/O object +- * +- * @mc_io: MC I/O object to destroy +- */ +-void fsl_destroy_mc_io(struct fsl_mc_io *mc_io) +-{ +- struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; +- +- if (dpmcp_dev) +- fsl_mc_io_unset_dpmcp(mc_io); +- +- devm_iounmap(mc_io->dev, mc_io->portal_virt_addr); +- devm_release_mem_region(mc_io->dev, +- mc_io->portal_phys_addr, +- mc_io->portal_size); +- +- mc_io->portal_virt_addr = NULL; +- devm_kfree(mc_io->dev, mc_io); +-} +- +-/** +- * fsl_mc_portal_allocate - Allocates an MC portal +- * +- * @mc_dev: MC device for which the MC portal is to be allocated +- * @mc_io_flags: Flags for the fsl_mc_io object that wraps the allocated +- * MC portal. +- * @new_mc_io: Pointer to area where the pointer to the fsl_mc_io object +- * that wraps the allocated MC portal is to be returned +- * +- * This function allocates an MC portal from the device's parent DPRC, +- * from the corresponding MC bus' pool of MC portals and wraps +- * it in a new fsl_mc_io object. If 'mc_dev' is a DPRC itself, the +- * portal is allocated from its own MC bus. +- */ +-int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, +- u16 mc_io_flags, +- struct fsl_mc_io **new_mc_io) +-{ +- struct fsl_mc_device *mc_bus_dev; +- struct fsl_mc_bus *mc_bus; +- phys_addr_t mc_portal_phys_addr; +- size_t mc_portal_size; +- struct fsl_mc_device *dpmcp_dev; +- int error = -EINVAL; +- struct fsl_mc_resource *resource = NULL; +- struct fsl_mc_io *mc_io = NULL; +- +- if (mc_dev->flags & FSL_MC_IS_DPRC) { +- mc_bus_dev = mc_dev; +- } else { +- if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent))) +- return error; +- +- mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); +- } +- +- mc_bus = to_fsl_mc_bus(mc_bus_dev); +- *new_mc_io = NULL; +- error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_DPMCP, &resource); +- if (error < 0) +- return error; +- +- error = -EINVAL; +- dpmcp_dev = resource->data; +- if (WARN_ON(!dpmcp_dev)) +- goto error_cleanup_resource; +- +- if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR || +- (dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR && +- dpmcp_dev->obj_desc.ver_minor < DPMCP_MIN_VER_MINOR)) { +- dev_err(&dpmcp_dev->dev, +- "ERROR: Version %d.%d of DPMCP not supported.\n", +- dpmcp_dev->obj_desc.ver_major, +- dpmcp_dev->obj_desc.ver_minor); +- error = -ENOTSUPP; +- goto error_cleanup_resource; +- } +- +- if (WARN_ON(dpmcp_dev->obj_desc.region_count == 0)) +- goto error_cleanup_resource; +- +- mc_portal_phys_addr = dpmcp_dev->regions[0].start; +- mc_portal_size = dpmcp_dev->regions[0].end - +- dpmcp_dev->regions[0].start + 1; +- +- if (WARN_ON(mc_portal_size != mc_bus_dev->mc_io->portal_size)) +- goto error_cleanup_resource; +- +- error = fsl_create_mc_io(&mc_bus_dev->dev, +- mc_portal_phys_addr, +- mc_portal_size, dpmcp_dev, +- mc_io_flags, &mc_io); +- if (error < 0) +- goto error_cleanup_resource; +- +- *new_mc_io = mc_io; +- return 0; +- +-error_cleanup_resource: +- fsl_mc_resource_free(resource); +- return error; +-} +-EXPORT_SYMBOL_GPL(fsl_mc_portal_allocate); +- +-/** +- * fsl_mc_portal_free - Returns an MC portal to the pool of free MC portals +- * of a given MC bus +- * +- * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free +- */ +-void fsl_mc_portal_free(struct fsl_mc_io *mc_io) +-{ +- struct fsl_mc_device *dpmcp_dev; +- struct fsl_mc_resource *resource; +- +- /* +- * Every mc_io obtained by calling fsl_mc_portal_allocate() is supposed +- * to have a DPMCP object associated with. +- */ +- dpmcp_dev = mc_io->dpmcp_dev; +- if (WARN_ON(!dpmcp_dev)) +- return; +- +- resource = dpmcp_dev->resource; +- if (WARN_ON(!resource || resource->type != FSL_MC_POOL_DPMCP)) +- return; +- +- if (WARN_ON(resource->data != dpmcp_dev)) +- return; +- +- fsl_destroy_mc_io(mc_io); +- fsl_mc_resource_free(resource); +-} +-EXPORT_SYMBOL_GPL(fsl_mc_portal_free); +- +-/** +- * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object +- * +- * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free +- */ +-int fsl_mc_portal_reset(struct fsl_mc_io *mc_io) +-{ +- int error; +- struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; +- +- if (WARN_ON(!dpmcp_dev)) +- return -EINVAL; +- +- error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle); +- if (error < 0) { +- dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error); +- return error; +- } +- +- return 0; +-} +-EXPORT_SYMBOL_GPL(fsl_mc_portal_reset); +--- /dev/null ++++ b/drivers/bus/fsl-mc/mc-io.c +@@ -0,0 +1,268 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright 2013-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: -@@ -11,7 +12,6 @@ - * names of any contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * -- * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") as published by the Free Software - * Foundation, either version 2 of that License or (at your option) any -@@ -32,7 +32,8 @@ - #include "../include/mc-sys.h" - #include "../include/mc-cmd.h" - #include "../include/dpbp.h" --#include "../include/dpbp-cmd.h" ++ * ++ */ ++ ++#include <linux/io.h> ++#include <linux/fsl/mc.h> ++ ++#include "fsl-mc-private.h" ++ ++static int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io, ++ struct fsl_mc_device *dpmcp_dev) ++{ ++ int error; ++ ++ if (mc_io->dpmcp_dev) ++ return -EINVAL; ++ ++ if (dpmcp_dev->mc_io) ++ return -EINVAL; ++ ++ error = dpmcp_open(mc_io, ++ 0, ++ dpmcp_dev->obj_desc.id, ++ &dpmcp_dev->mc_handle); ++ if (error < 0) ++ return error; ++ ++ mc_io->dpmcp_dev = dpmcp_dev; ++ dpmcp_dev->mc_io = mc_io; ++ return 0; ++} ++ ++static void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io) ++{ ++ int error; ++ struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; ++ ++ error = dpmcp_close(mc_io, ++ 0, ++ dpmcp_dev->mc_handle); ++ if (error < 0) { ++ dev_err(&dpmcp_dev->dev, "dpmcp_close() failed: %d\n", ++ error); ++ } ++ ++ mc_io->dpmcp_dev = NULL; ++ dpmcp_dev->mc_io = NULL; ++} ++ ++/** ++ * Creates an MC I/O object ++ * ++ * @dev: device to be associated with the MC I/O object ++ * @mc_portal_phys_addr: physical address of the MC portal to use ++ * @mc_portal_size: size in bytes of the MC portal ++ * @dpmcp-dev: Pointer to the DPMCP object associated with this MC I/O ++ * object or NULL if none. ++ * @flags: flags for the new MC I/O object ++ * @new_mc_io: Area to return pointer to newly created MC I/O object ++ * ++ * Returns '0' on Success; Error code otherwise. ++ */ ++int __must_check fsl_create_mc_io(struct device *dev, ++ phys_addr_t mc_portal_phys_addr, ++ u32 mc_portal_size, ++ struct fsl_mc_device *dpmcp_dev, ++ u32 flags, struct fsl_mc_io **new_mc_io) ++{ ++ int error; ++ struct fsl_mc_io *mc_io; ++ void __iomem *mc_portal_virt_addr; ++ struct resource *res; ++ ++ mc_io = devm_kzalloc(dev, sizeof(*mc_io), GFP_KERNEL); ++ if (!mc_io) ++ return -ENOMEM; ++ ++ mc_io->dev = dev; ++ mc_io->flags = flags; ++ mc_io->portal_phys_addr = mc_portal_phys_addr; ++ mc_io->portal_size = mc_portal_size; ++ if (flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) ++ spin_lock_init(&mc_io->spinlock); ++ else ++ mutex_init(&mc_io->mutex); ++ ++ res = devm_request_mem_region(dev, ++ mc_portal_phys_addr, ++ mc_portal_size, ++ "mc_portal"); ++ if (!res) { ++ dev_err(dev, ++ "devm_request_mem_region failed for MC portal %pa\n", ++ &mc_portal_phys_addr); ++ return -EBUSY; ++ } ++ ++ mc_portal_virt_addr = devm_ioremap_nocache(dev, ++ mc_portal_phys_addr, ++ mc_portal_size); ++ if (!mc_portal_virt_addr) { ++ dev_err(dev, ++ "devm_ioremap_nocache failed for MC portal %pa\n", ++ &mc_portal_phys_addr); ++ return -ENXIO; ++ } ++ ++ mc_io->portal_virt_addr = mc_portal_virt_addr; ++ if (dpmcp_dev) { ++ error = fsl_mc_io_set_dpmcp(mc_io, dpmcp_dev); ++ if (error < 0) ++ goto error_destroy_mc_io; ++ } ++ ++ *new_mc_io = mc_io; ++ return 0; ++ ++error_destroy_mc_io: ++ fsl_destroy_mc_io(mc_io); ++ return error; ++} ++ ++/** ++ * Destroys an MC I/O object ++ * ++ * @mc_io: MC I/O object to destroy ++ */ ++void fsl_destroy_mc_io(struct fsl_mc_io *mc_io) ++{ ++ struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; ++ ++ if (dpmcp_dev) ++ fsl_mc_io_unset_dpmcp(mc_io); ++ ++ devm_iounmap(mc_io->dev, mc_io->portal_virt_addr); ++ devm_release_mem_region(mc_io->dev, ++ mc_io->portal_phys_addr, ++ mc_io->portal_size); ++ ++ mc_io->portal_virt_addr = NULL; ++ devm_kfree(mc_io->dev, mc_io); ++} ++ ++/** ++ * fsl_mc_portal_allocate - Allocates an MC portal ++ * ++ * @mc_dev: MC device for which the MC portal is to be allocated ++ * @mc_io_flags: Flags for the fsl_mc_io object that wraps the allocated ++ * MC portal. ++ * @new_mc_io: Pointer to area where the pointer to the fsl_mc_io object ++ * that wraps the allocated MC portal is to be returned ++ * ++ * This function allocates an MC portal from the device's parent DPRC, ++ * from the corresponding MC bus' pool of MC portals and wraps ++ * it in a new fsl_mc_io object. If 'mc_dev' is a DPRC itself, the ++ * portal is allocated from its own MC bus. ++ */ ++int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, ++ u16 mc_io_flags, ++ struct fsl_mc_io **new_mc_io) ++{ ++ struct fsl_mc_device *mc_bus_dev; ++ struct fsl_mc_bus *mc_bus; ++ phys_addr_t mc_portal_phys_addr; ++ size_t mc_portal_size; ++ struct fsl_mc_device *dpmcp_dev; ++ int error = -EINVAL; ++ struct fsl_mc_resource *resource = NULL; ++ struct fsl_mc_io *mc_io = NULL; ++ ++ if (mc_dev->flags & FSL_MC_IS_DPRC) { ++ mc_bus_dev = mc_dev; ++ } else { ++ if (!dev_is_fsl_mc(mc_dev->dev.parent)) ++ return error; ++ ++ mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); ++ } ++ ++ mc_bus = to_fsl_mc_bus(mc_bus_dev); ++ *new_mc_io = NULL; ++ error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_DPMCP, &resource); ++ if (error < 0) ++ return error; ++ ++ error = -EINVAL; ++ dpmcp_dev = resource->data; ++ ++ if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR || ++ (dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR && ++ dpmcp_dev->obj_desc.ver_minor < DPMCP_MIN_VER_MINOR)) { ++ dev_err(&dpmcp_dev->dev, ++ "ERROR: Version %d.%d of DPMCP not supported.\n", ++ dpmcp_dev->obj_desc.ver_major, ++ dpmcp_dev->obj_desc.ver_minor); ++ error = -ENOTSUPP; ++ goto error_cleanup_resource; ++ } ++ ++ mc_portal_phys_addr = dpmcp_dev->regions[0].start; ++ mc_portal_size = resource_size(dpmcp_dev->regions); ++ ++ error = fsl_create_mc_io(&mc_bus_dev->dev, ++ mc_portal_phys_addr, ++ mc_portal_size, dpmcp_dev, ++ mc_io_flags, &mc_io); ++ if (error < 0) ++ goto error_cleanup_resource; ++ ++ *new_mc_io = mc_io; ++ return 0; ++ ++error_cleanup_resource: ++ fsl_mc_resource_free(resource); ++ return error; ++} ++EXPORT_SYMBOL_GPL(fsl_mc_portal_allocate); ++ ++/** ++ * fsl_mc_portal_free - Returns an MC portal to the pool of free MC portals ++ * of a given MC bus ++ * ++ * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free ++ */ ++void fsl_mc_portal_free(struct fsl_mc_io *mc_io) ++{ ++ struct fsl_mc_device *dpmcp_dev; ++ struct fsl_mc_resource *resource; ++ ++ /* ++ * Every mc_io obtained by calling fsl_mc_portal_allocate() is supposed ++ * to have a DPMCP object associated with. ++ */ ++ dpmcp_dev = mc_io->dpmcp_dev; ++ ++ resource = dpmcp_dev->resource; ++ if (!resource || resource->type != FSL_MC_POOL_DPMCP) ++ return; ++ ++ if (resource->data != dpmcp_dev) ++ return; ++ ++ fsl_destroy_mc_io(mc_io); ++ fsl_mc_resource_free(resource); ++} ++EXPORT_SYMBOL_GPL(fsl_mc_portal_free); ++ ++/** ++ * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object ++ * ++ * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free ++ */ ++int fsl_mc_portal_reset(struct fsl_mc_io *mc_io) ++{ ++ int error; ++ struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; ++ ++ error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle); ++ if (error < 0) { ++ dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error); ++ return error; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(fsl_mc_portal_reset); +--- a/drivers/staging/fsl-mc/bus/mc-sys.c ++++ /dev/null +@@ -1,317 +0,0 @@ +-/* Copyright 2013-2014 Freescale Semiconductor Inc. +- * +- * I/O services to send MC commands to the MC hardware +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of the above-listed copyright holders nor the +- * names of any contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +- * POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#include <linux/delay.h> +-#include <linux/slab.h> +-#include <linux/ioport.h> +-#include <linux/device.h> +-#include <linux/io.h> +-#include "../include/mc-sys.h" +-#include "../include/mc-cmd.h" +-#include "../include/mc.h" +- +-#include "dpmcp.h" +- +-/** +- * Timeout in milliseconds to wait for the completion of an MC command +- */ +-#define MC_CMD_COMPLETION_TIMEOUT_MS 500 +- +-/* +- * usleep_range() min and max values used to throttle down polling +- * iterations while waiting for MC command completion +- */ +-#define MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS 10 +-#define MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS 500 +- +-static enum mc_cmd_status mc_cmd_hdr_read_status(struct mc_command *cmd) +-{ +- struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header; +- +- return (enum mc_cmd_status)hdr->status; +-} +- +-static u16 mc_cmd_hdr_read_cmdid(struct mc_command *cmd) +-{ +- struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header; +- u16 cmd_id = le16_to_cpu(hdr->cmd_id); +- +- return (cmd_id & MC_CMD_HDR_CMDID_MASK) >> MC_CMD_HDR_CMDID_SHIFT; +-} +- +-static int mc_status_to_error(enum mc_cmd_status status) +-{ +- static const int mc_status_to_error_map[] = { +- [MC_CMD_STATUS_OK] = 0, +- [MC_CMD_STATUS_AUTH_ERR] = -EACCES, +- [MC_CMD_STATUS_NO_PRIVILEGE] = -EPERM, +- [MC_CMD_STATUS_DMA_ERR] = -EIO, +- [MC_CMD_STATUS_CONFIG_ERR] = -ENXIO, +- [MC_CMD_STATUS_TIMEOUT] = -ETIMEDOUT, +- [MC_CMD_STATUS_NO_RESOURCE] = -ENAVAIL, +- [MC_CMD_STATUS_NO_MEMORY] = -ENOMEM, +- [MC_CMD_STATUS_BUSY] = -EBUSY, +- [MC_CMD_STATUS_UNSUPPORTED_OP] = -ENOTSUPP, +- [MC_CMD_STATUS_INVALID_STATE] = -ENODEV, +- }; +- +- if (WARN_ON((u32)status >= ARRAY_SIZE(mc_status_to_error_map))) +- return -EINVAL; +- +- return mc_status_to_error_map[status]; +-} +- +-static const char *mc_status_to_string(enum mc_cmd_status status) +-{ +- static const char *const status_strings[] = { +- [MC_CMD_STATUS_OK] = "Command completed successfully", +- [MC_CMD_STATUS_READY] = "Command ready to be processed", +- [MC_CMD_STATUS_AUTH_ERR] = "Authentication error", +- [MC_CMD_STATUS_NO_PRIVILEGE] = "No privilege", +- [MC_CMD_STATUS_DMA_ERR] = "DMA or I/O error", +- [MC_CMD_STATUS_CONFIG_ERR] = "Configuration error", +- [MC_CMD_STATUS_TIMEOUT] = "Operation timed out", +- [MC_CMD_STATUS_NO_RESOURCE] = "No resources", +- [MC_CMD_STATUS_NO_MEMORY] = "No memory available", +- [MC_CMD_STATUS_BUSY] = "Device is busy", +- [MC_CMD_STATUS_UNSUPPORTED_OP] = "Unsupported operation", +- [MC_CMD_STATUS_INVALID_STATE] = "Invalid state" +- }; +- +- if ((unsigned int)status >= ARRAY_SIZE(status_strings)) +- return "Unknown MC error"; +- +- return status_strings[status]; +-} +- +-/** +- * mc_write_command - writes a command to a Management Complex (MC) portal +- * +- * @portal: pointer to an MC portal +- * @cmd: pointer to a filled command +- */ +-static inline void mc_write_command(struct mc_command __iomem *portal, +- struct mc_command *cmd) +-{ +- int i; +- +- /* copy command parameters into the portal */ +- for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++) +- __raw_writeq(cmd->params[i], &portal->params[i]); +- __iowmb(); +- +- /* submit the command by writing the header */ +- __raw_writeq(cmd->header, &portal->header); +-} +- +-/** +- * mc_read_response - reads the response for the last MC command from a +- * Management Complex (MC) portal +- * +- * @portal: pointer to an MC portal +- * @resp: pointer to command response buffer +- * +- * Returns MC_CMD_STATUS_OK on Success; Error code otherwise. +- */ +-static inline enum mc_cmd_status mc_read_response(struct mc_command __iomem * +- portal, +- struct mc_command *resp) +-{ +- int i; +- enum mc_cmd_status status; +- +- /* Copy command response header from MC portal: */ +- __iormb(); +- resp->header = __raw_readq(&portal->header); +- __iormb(); +- status = mc_cmd_hdr_read_status(resp); +- if (status != MC_CMD_STATUS_OK) +- return status; +- +- /* Copy command response data from MC portal: */ +- for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++) +- resp->params[i] = __raw_readq(&portal->params[i]); +- __iormb(); +- +- return status; +-} +- +-/** +- * Waits for the completion of an MC command doing preemptible polling. +- * uslepp_range() is called between polling iterations. +- * +- * @mc_io: MC I/O object to be used +- * @cmd: command buffer to receive MC response +- * @mc_status: MC command completion status +- */ +-static int mc_polling_wait_preemptible(struct fsl_mc_io *mc_io, +- struct mc_command *cmd, +- enum mc_cmd_status *mc_status) +-{ +- enum mc_cmd_status status; +- unsigned long jiffies_until_timeout = +- jiffies + msecs_to_jiffies(MC_CMD_COMPLETION_TIMEOUT_MS); +- +- /* +- * Wait for response from the MC hardware: +- */ +- for (;;) { +- status = mc_read_response(mc_io->portal_virt_addr, cmd); +- if (status != MC_CMD_STATUS_READY) +- break; +- +- /* +- * TODO: When MC command completion interrupts are supported +- * call wait function here instead of usleep_range() +- */ +- usleep_range(MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS, +- MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS); +- +- if (time_after_eq(jiffies, jiffies_until_timeout)) { +- dev_dbg(mc_io->dev, +- "MC command timed out (portal: %#llx, obj handle: %#x, command: %#x)\n", +- mc_io->portal_phys_addr, +- (unsigned int)mc_cmd_hdr_read_token(cmd), +- (unsigned int)mc_cmd_hdr_read_cmdid(cmd)); +- +- return -ETIMEDOUT; +- } +- } +- +- *mc_status = status; +- return 0; +-} +- +-/** +- * Waits for the completion of an MC command doing atomic polling. +- * udelay() is called between polling iterations. +- * +- * @mc_io: MC I/O object to be used +- * @cmd: command buffer to receive MC response +- * @mc_status: MC command completion status +- */ +-static int mc_polling_wait_atomic(struct fsl_mc_io *mc_io, +- struct mc_command *cmd, +- enum mc_cmd_status *mc_status) +-{ +- enum mc_cmd_status status; +- unsigned long timeout_usecs = MC_CMD_COMPLETION_TIMEOUT_MS * 1000; +- +- BUILD_BUG_ON((MC_CMD_COMPLETION_TIMEOUT_MS * 1000) % +- MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS != 0); +- +- for (;;) { +- status = mc_read_response(mc_io->portal_virt_addr, cmd); +- if (status != MC_CMD_STATUS_READY) +- break; +- +- udelay(MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS); +- timeout_usecs -= MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS; +- if (timeout_usecs == 0) { +- dev_dbg(mc_io->dev, +- "MC command timed out (portal: %#llx, obj handle: %#x, command: %#x)\n", +- mc_io->portal_phys_addr, +- (unsigned int)mc_cmd_hdr_read_token(cmd), +- (unsigned int)mc_cmd_hdr_read_cmdid(cmd)); +- +- return -ETIMEDOUT; +- } +- } +- +- *mc_status = status; +- return 0; +-} +- +-/** +- * Sends a command to the MC device using the given MC I/O object +- * +- * @mc_io: MC I/O object to be used +- * @cmd: command to be sent +- * +- * Returns '0' on Success; Error code otherwise. +- */ +-int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd) +-{ +- int error; +- enum mc_cmd_status status; +- unsigned long irq_flags = 0; +- +- if (WARN_ON(in_irq() && +- !(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL))) +- return -EINVAL; +- +- if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) +- spin_lock_irqsave(&mc_io->spinlock, irq_flags); +- else +- mutex_lock(&mc_io->mutex); +- +- /* +- * Send command to the MC hardware: +- */ +- mc_write_command(mc_io->portal_virt_addr, cmd); +- +- /* +- * Wait for response from the MC hardware: +- */ +- if (!(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)) +- error = mc_polling_wait_preemptible(mc_io, cmd, &status); +- else +- error = mc_polling_wait_atomic(mc_io, cmd, &status); +- +- if (error < 0) +- goto common_exit; +- +- if (status != MC_CMD_STATUS_OK) { +- dev_dbg(mc_io->dev, +- "MC command failed: portal: %#llx, obj handle: %#x, command: %#x, status: %s (%#x)\n", +- mc_io->portal_phys_addr, +- (unsigned int)mc_cmd_hdr_read_token(cmd), +- (unsigned int)mc_cmd_hdr_read_cmdid(cmd), +- mc_status_to_string(status), +- (unsigned int)status); +- +- error = mc_status_to_error(status); +- goto common_exit; +- } +- +- error = 0; +-common_exit: +- if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) +- spin_unlock_irqrestore(&mc_io->spinlock, irq_flags); +- else +- mutex_unlock(&mc_io->mutex); +- +- return error; +-} +-EXPORT_SYMBOL(mc_send_command); +--- /dev/null ++++ b/drivers/bus/fsl-mc/mc-sys.c +@@ -0,0 +1,296 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright 2013-2016 Freescale Semiconductor Inc. ++ * ++ * I/O services to send MC commands to the MC hardware ++ * ++ */ ++ ++#include <linux/delay.h> ++#include <linux/slab.h> ++#include <linux/ioport.h> ++#include <linux/device.h> ++#include <linux/io.h> ++#include <linux/io-64-nonatomic-hi-lo.h> ++#include <linux/fsl/mc.h> ++ ++#include "fsl-mc-private.h" ++ ++/** ++ * Timeout in milliseconds to wait for the completion of an MC command ++ */ ++#define MC_CMD_COMPLETION_TIMEOUT_MS 15000 + -+#include "dpbp-cmd.h" ++/* ++ * usleep_range() min and max values used to throttle down polling ++ * iterations while waiting for MC command completion ++ */ ++#define MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS 10 ++#define MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS 500 ++ ++static enum mc_cmd_status mc_cmd_hdr_read_status(struct fsl_mc_command *cmd) ++{ ++ struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header; ++ ++ return (enum mc_cmd_status)hdr->status; ++} ++ ++static u16 mc_cmd_hdr_read_cmdid(struct fsl_mc_command *cmd) ++{ ++ struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header; ++ u16 cmd_id = le16_to_cpu(hdr->cmd_id); ++ ++ return cmd_id; ++} ++ ++static int mc_status_to_error(enum mc_cmd_status status) ++{ ++ static const int mc_status_to_error_map[] = { ++ [MC_CMD_STATUS_OK] = 0, ++ [MC_CMD_STATUS_AUTH_ERR] = -EACCES, ++ [MC_CMD_STATUS_NO_PRIVILEGE] = -EPERM, ++ [MC_CMD_STATUS_DMA_ERR] = -EIO, ++ [MC_CMD_STATUS_CONFIG_ERR] = -ENXIO, ++ [MC_CMD_STATUS_TIMEOUT] = -ETIMEDOUT, ++ [MC_CMD_STATUS_NO_RESOURCE] = -ENAVAIL, ++ [MC_CMD_STATUS_NO_MEMORY] = -ENOMEM, ++ [MC_CMD_STATUS_BUSY] = -EBUSY, ++ [MC_CMD_STATUS_UNSUPPORTED_OP] = -ENOTSUPP, ++ [MC_CMD_STATUS_INVALID_STATE] = -ENODEV, ++ }; ++ ++ if ((u32)status >= ARRAY_SIZE(mc_status_to_error_map)) ++ return -EINVAL; ++ ++ return mc_status_to_error_map[status]; ++} ++ ++static const char *mc_status_to_string(enum mc_cmd_status status) ++{ ++ static const char *const status_strings[] = { ++ [MC_CMD_STATUS_OK] = "Command completed successfully", ++ [MC_CMD_STATUS_READY] = "Command ready to be processed", ++ [MC_CMD_STATUS_AUTH_ERR] = "Authentication error", ++ [MC_CMD_STATUS_NO_PRIVILEGE] = "No privilege", ++ [MC_CMD_STATUS_DMA_ERR] = "DMA or I/O error", ++ [MC_CMD_STATUS_CONFIG_ERR] = "Configuration error", ++ [MC_CMD_STATUS_TIMEOUT] = "Operation timed out", ++ [MC_CMD_STATUS_NO_RESOURCE] = "No resources", ++ [MC_CMD_STATUS_NO_MEMORY] = "No memory available", ++ [MC_CMD_STATUS_BUSY] = "Device is busy", ++ [MC_CMD_STATUS_UNSUPPORTED_OP] = "Unsupported operation", ++ [MC_CMD_STATUS_INVALID_STATE] = "Invalid state" ++ }; ++ ++ if ((unsigned int)status >= ARRAY_SIZE(status_strings)) ++ return "Unknown MC error"; ++ ++ return status_strings[status]; ++} ++ ++/** ++ * mc_write_command - writes a command to a Management Complex (MC) portal ++ * ++ * @portal: pointer to an MC portal ++ * @cmd: pointer to a filled command ++ */ ++static inline void mc_write_command(struct fsl_mc_command __iomem *portal, ++ struct fsl_mc_command *cmd) ++{ ++ int i; ++ ++ /* copy command parameters into the portal */ ++ for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++) ++ /* ++ * Data is already in the expected LE byte-order. Do an ++ * extra LE -> CPU conversion so that the CPU -> LE done in ++ * the device io write api puts it back in the right order. ++ */ ++ writeq_relaxed(le64_to_cpu(cmd->params[i]), &portal->params[i]); ++ ++ /* submit the command by writing the header */ ++ writeq(le64_to_cpu(cmd->header), &portal->header); ++} ++ ++/** ++ * mc_read_response - reads the response for the last MC command from a ++ * Management Complex (MC) portal ++ * ++ * @portal: pointer to an MC portal ++ * @resp: pointer to command response buffer ++ * ++ * Returns MC_CMD_STATUS_OK on Success; Error code otherwise. ++ */ ++static inline enum mc_cmd_status mc_read_response(struct fsl_mc_command __iomem ++ *portal, ++ struct fsl_mc_command *resp) ++{ ++ int i; ++ enum mc_cmd_status status; ++ ++ /* Copy command response header from MC portal: */ ++ resp->header = cpu_to_le64(readq_relaxed(&portal->header)); ++ status = mc_cmd_hdr_read_status(resp); ++ if (status != MC_CMD_STATUS_OK) ++ return status; ++ ++ /* Copy command response data from MC portal: */ ++ for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++) ++ /* ++ * Data is expected to be in LE byte-order. Do an ++ * extra CPU -> LE to revert the LE -> CPU done in ++ * the device io read api. ++ */ ++ resp->params[i] = ++ cpu_to_le64(readq_relaxed(&portal->params[i])); ++ ++ return status; ++} ++ ++/** ++ * Waits for the completion of an MC command doing preemptible polling. ++ * uslepp_range() is called between polling iterations. ++ * ++ * @mc_io: MC I/O object to be used ++ * @cmd: command buffer to receive MC response ++ * @mc_status: MC command completion status ++ */ ++static int mc_polling_wait_preemptible(struct fsl_mc_io *mc_io, ++ struct fsl_mc_command *cmd, ++ enum mc_cmd_status *mc_status) ++{ ++ enum mc_cmd_status status; ++ unsigned long jiffies_until_timeout = ++ jiffies + msecs_to_jiffies(MC_CMD_COMPLETION_TIMEOUT_MS); ++ ++ /* ++ * Wait for response from the MC hardware: ++ */ ++ for (;;) { ++ status = mc_read_response(mc_io->portal_virt_addr, cmd); ++ if (status != MC_CMD_STATUS_READY) ++ break; ++ ++ /* ++ * TODO: When MC command completion interrupts are supported ++ * call wait function here instead of usleep_range() ++ */ ++ usleep_range(MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS, ++ MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS); ++ ++ if (time_after_eq(jiffies, jiffies_until_timeout)) { ++ dev_dbg(mc_io->dev, ++ "MC command timed out (portal: %pa, dprc handle: %#x, command: %#x)\n", ++ &mc_io->portal_phys_addr, ++ (unsigned int)mc_cmd_hdr_read_token(cmd), ++ (unsigned int)mc_cmd_hdr_read_cmdid(cmd)); ++ ++ return -ETIMEDOUT; ++ } ++ } ++ ++ *mc_status = status; ++ return 0; ++} ++ ++/** ++ * Waits for the completion of an MC command doing atomic polling. ++ * udelay() is called between polling iterations. ++ * ++ * @mc_io: MC I/O object to be used ++ * @cmd: command buffer to receive MC response ++ * @mc_status: MC command completion status ++ */ ++static int mc_polling_wait_atomic(struct fsl_mc_io *mc_io, ++ struct fsl_mc_command *cmd, ++ enum mc_cmd_status *mc_status) ++{ ++ enum mc_cmd_status status; ++ unsigned long timeout_usecs = MC_CMD_COMPLETION_TIMEOUT_MS * 1000; ++ ++ BUILD_BUG_ON((MC_CMD_COMPLETION_TIMEOUT_MS * 1000) % ++ MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS != 0); ++ ++ for (;;) { ++ status = mc_read_response(mc_io->portal_virt_addr, cmd); ++ if (status != MC_CMD_STATUS_READY) ++ break; ++ ++ udelay(MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS); ++ timeout_usecs -= MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS; ++ if (timeout_usecs == 0) { ++ dev_dbg(mc_io->dev, ++ "MC command timed out (portal: %pa, dprc handle: %#x, command: %#x)\n", ++ &mc_io->portal_phys_addr, ++ (unsigned int)mc_cmd_hdr_read_token(cmd), ++ (unsigned int)mc_cmd_hdr_read_cmdid(cmd)); ++ ++ return -ETIMEDOUT; ++ } ++ } ++ ++ *mc_status = status; ++ return 0; ++} ++ ++/** ++ * Sends a command to the MC device using the given MC I/O object ++ * ++ * @mc_io: MC I/O object to be used ++ * @cmd: command to be sent ++ * ++ * Returns '0' on Success; Error code otherwise. ++ */ ++int mc_send_command(struct fsl_mc_io *mc_io, struct fsl_mc_command *cmd) ++{ ++ int error; ++ enum mc_cmd_status status; ++ unsigned long irq_flags = 0; ++ ++ if (in_irq() && !(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)) ++ return -EINVAL; ++ ++ if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) ++ spin_lock_irqsave(&mc_io->spinlock, irq_flags); ++ else ++ mutex_lock(&mc_io->mutex); ++ ++ /* ++ * Send command to the MC hardware: ++ */ ++ mc_write_command(mc_io->portal_virt_addr, cmd); ++ ++ /* ++ * Wait for response from the MC hardware: ++ */ ++ if (!(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)) ++ error = mc_polling_wait_preemptible(mc_io, cmd, &status); ++ else ++ error = mc_polling_wait_atomic(mc_io, cmd, &status); ++ ++ if (error < 0) ++ goto common_exit; ++ ++ if (status != MC_CMD_STATUS_OK) { ++ dev_dbg(mc_io->dev, ++ "MC command failed: portal: %pa, dprc handle: %#x, command: %#x, status: %s (%#x)\n", ++ &mc_io->portal_phys_addr, ++ (unsigned int)mc_cmd_hdr_read_token(cmd), ++ (unsigned int)mc_cmd_hdr_read_cmdid(cmd), ++ mc_status_to_string(status), ++ (unsigned int)status); ++ ++ error = mc_status_to_error(status); ++ goto common_exit; ++ } ++ ++ error = 0; ++common_exit: ++ if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) ++ spin_unlock_irqrestore(&mc_io->spinlock, irq_flags); ++ else ++ mutex_unlock(&mc_io->mutex); ++ ++ return error; ++} ++EXPORT_SYMBOL_GPL(mc_send_command); +--- a/drivers/irqchip/Kconfig ++++ b/drivers/irqchip/Kconfig +@@ -41,6 +41,12 @@ config ARM_GIC_V3_ITS + depends on PCI_MSI + select ACPI_IORT if ACPI - /** - * dpbp_open() - Open a control session for the specified object. -@@ -105,74 +106,6 @@ int dpbp_close(struct fsl_mc_io *mc_io, - EXPORT_SYMBOL(dpbp_close); ++config ARM_GIC_V3_ITS_FSL_MC ++ bool ++ depends on ARM_GIC_V3_ITS ++ depends on FSL_MC_BUS ++ default ARM_GIC_V3_ITS ++ + config ARM_NVIC + bool + select IRQ_DOMAIN +--- a/drivers/irqchip/Makefile ++++ b/drivers/irqchip/Makefile +@@ -29,6 +29,7 @@ obj-$(CONFIG_ARCH_REALVIEW) += irq-gic- + obj-$(CONFIG_ARM_GIC_V2M) += irq-gic-v2m.o + obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-common.o + obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v3-its-pci-msi.o irq-gic-v3-its-platform-msi.o ++obj-$(CONFIG_ARM_GIC_V3_ITS_FSL_MC) += irq-gic-v3-its-fsl-mc-msi.o + obj-$(CONFIG_PARTITION_PERCPU) += irq-partition-percpu.o + obj-$(CONFIG_HISILICON_IRQ_MBIGEN) += irq-mbigen.o + obj-$(CONFIG_ARM_NVIC) += irq-nvic.o +--- a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c ++++ /dev/null +@@ -1,126 +0,0 @@ +-/* +- * Freescale Management Complex (MC) bus driver MSI support +- * +- * Copyright (C) 2015 Freescale Semiconductor, Inc. +- * Author: German Rivera <German.Rivera@freescale.com> +- * +- * 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 <linux/of_device.h> +-#include <linux/of_address.h> +-#include <linux/irqchip/arm-gic-v3.h> +-#include <linux/irq.h> +-#include <linux/msi.h> +-#include <linux/of.h> +-#include <linux/of_irq.h> +-#include "../include/mc-bus.h" +-#include "fsl-mc-private.h" +- +-static struct irq_chip its_msi_irq_chip = { +- .name = "fsl-mc-bus-msi", +- .irq_mask = irq_chip_mask_parent, +- .irq_unmask = irq_chip_unmask_parent, +- .irq_eoi = irq_chip_eoi_parent, +- .irq_set_affinity = msi_domain_set_affinity +-}; +- +-static int its_fsl_mc_msi_prepare(struct irq_domain *msi_domain, +- struct device *dev, +- int nvec, msi_alloc_info_t *info) +-{ +- struct fsl_mc_device *mc_bus_dev; +- struct msi_domain_info *msi_info; +- +- if (WARN_ON(!dev_is_fsl_mc(dev))) +- return -EINVAL; +- +- mc_bus_dev = to_fsl_mc_device(dev); +- if (WARN_ON(!(mc_bus_dev->flags & FSL_MC_IS_DPRC))) +- return -EINVAL; +- +- /* +- * Set the device Id to be passed to the GIC-ITS: +- * +- * NOTE: This device id corresponds to the IOMMU stream ID +- * associated with the DPRC object (ICID). +- */ +- info->scratchpad[0].ul = mc_bus_dev->icid; +- msi_info = msi_get_domain_info(msi_domain->parent); +- return msi_info->ops->msi_prepare(msi_domain->parent, dev, nvec, info); +-} +- +-static struct msi_domain_ops its_fsl_mc_msi_ops = { +- .msi_prepare = its_fsl_mc_msi_prepare, +-}; +- +-static struct msi_domain_info its_fsl_mc_msi_domain_info = { +- .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS), +- .ops = &its_fsl_mc_msi_ops, +- .chip = &its_msi_irq_chip, +-}; +- +-static const struct of_device_id its_device_id[] = { +- { .compatible = "arm,gic-v3-its", }, +- {}, +-}; +- +-int __init its_fsl_mc_msi_init(void) +-{ +- struct device_node *np; +- struct irq_domain *parent; +- struct irq_domain *mc_msi_domain; +- +- for (np = of_find_matching_node(NULL, its_device_id); np; +- np = of_find_matching_node(np, its_device_id)) { +- if (!of_device_is_available(np)) +- continue; +- if (!of_property_read_bool(np, "msi-controller")) +- continue; +- +- parent = irq_find_matching_host(np, DOMAIN_BUS_NEXUS); +- if (!parent || !msi_get_domain_info(parent)) { +- pr_err("%s: unable to locate ITS domain\n", +- np->full_name); +- continue; +- } +- +- mc_msi_domain = fsl_mc_msi_create_irq_domain( +- of_node_to_fwnode(np), +- &its_fsl_mc_msi_domain_info, +- parent); +- if (!mc_msi_domain) { +- pr_err("%s: unable to create fsl-mc domain\n", +- np->full_name); +- continue; +- } +- +- WARN_ON(mc_msi_domain-> +- host_data != &its_fsl_mc_msi_domain_info); +- +- pr_info("fsl-mc MSI: %s domain created\n", np->full_name); +- } +- +- return 0; +-} +- +-void its_fsl_mc_msi_cleanup(void) +-{ +- struct device_node *np; +- +- for (np = of_find_matching_node(NULL, its_device_id); np; +- np = of_find_matching_node(np, its_device_id)) { +- struct irq_domain *mc_msi_domain = irq_find_matching_host( +- np, +- DOMAIN_BUS_FSL_MC_MSI); +- +- if (!of_property_read_bool(np, "msi-controller")) +- continue; +- +- if (mc_msi_domain && +- mc_msi_domain->host_data == &its_fsl_mc_msi_domain_info) +- irq_domain_remove(mc_msi_domain); +- } +-} +--- /dev/null ++++ b/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c +@@ -0,0 +1,98 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Freescale Management Complex (MC) bus driver MSI support ++ * ++ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. ++ * Author: German Rivera <German.Rivera@freescale.com> ++ * ++ */ ++ ++#include <linux/of_device.h> ++#include <linux/of_address.h> ++#include <linux/irq.h> ++#include <linux/msi.h> ++#include <linux/of.h> ++#include <linux/of_irq.h> ++#include <linux/fsl/mc.h> ++ ++static struct irq_chip its_msi_irq_chip = { ++ .name = "ITS-fMSI", ++ .irq_mask = irq_chip_mask_parent, ++ .irq_unmask = irq_chip_unmask_parent, ++ .irq_eoi = irq_chip_eoi_parent, ++ .irq_set_affinity = msi_domain_set_affinity ++}; ++ ++static int its_fsl_mc_msi_prepare(struct irq_domain *msi_domain, ++ struct device *dev, ++ int nvec, msi_alloc_info_t *info) ++{ ++ struct fsl_mc_device *mc_bus_dev; ++ struct msi_domain_info *msi_info; ++ ++ if (!dev_is_fsl_mc(dev)) ++ return -EINVAL; ++ ++ mc_bus_dev = to_fsl_mc_device(dev); ++ if (!(mc_bus_dev->flags & FSL_MC_IS_DPRC)) ++ return -EINVAL; ++ ++ /* ++ * Set the device Id to be passed to the GIC-ITS: ++ * ++ * NOTE: This device id corresponds to the IOMMU stream ID ++ * associated with the DPRC object (ICID). ++ */ ++ info->scratchpad[0].ul = mc_bus_dev->icid; ++ msi_info = msi_get_domain_info(msi_domain->parent); ++ return msi_info->ops->msi_prepare(msi_domain->parent, dev, nvec, info); ++} ++ ++static struct msi_domain_ops its_fsl_mc_msi_ops __ro_after_init = { ++ .msi_prepare = its_fsl_mc_msi_prepare, ++}; ++ ++static struct msi_domain_info its_fsl_mc_msi_domain_info = { ++ .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS), ++ .ops = &its_fsl_mc_msi_ops, ++ .chip = &its_msi_irq_chip, ++}; ++ ++static const struct of_device_id its_device_id[] = { ++ { .compatible = "arm,gic-v3-its", }, ++ {}, ++}; ++ ++static int __init its_fsl_mc_msi_init(void) ++{ ++ struct device_node *np; ++ struct irq_domain *parent; ++ struct irq_domain *mc_msi_domain; ++ ++ for (np = of_find_matching_node(NULL, its_device_id); np; ++ np = of_find_matching_node(np, its_device_id)) { ++ if (!of_property_read_bool(np, "msi-controller")) ++ continue; ++ ++ parent = irq_find_matching_host(np, DOMAIN_BUS_NEXUS); ++ if (!parent || !msi_get_domain_info(parent)) { ++ pr_err("%pOF: unable to locate ITS domain\n", np); ++ continue; ++ } ++ ++ mc_msi_domain = fsl_mc_msi_create_irq_domain( ++ of_node_to_fwnode(np), ++ &its_fsl_mc_msi_domain_info, ++ parent); ++ if (!mc_msi_domain) { ++ pr_err("%pOF: unable to create fsl-mc domain\n", np); ++ continue; ++ } ++ ++ pr_info("fsl-mc MSI: %pOF domain created\n", np); ++ } ++ ++ return 0; ++} ++ ++early_initcall(its_fsl_mc_msi_init); +--- a/drivers/staging/fsl-mc/Kconfig ++++ b/drivers/staging/fsl-mc/Kconfig +@@ -1 +1,2 @@ ++# SPDX-License-Identifier: GPL-2.0 + source "drivers/staging/fsl-mc/bus/Kconfig" +--- a/drivers/staging/fsl-mc/Makefile ++++ b/drivers/staging/fsl-mc/Makefile +@@ -1,2 +1,3 @@ ++# SPDX-License-Identifier: GPL-2.0 + # Freescale Management Complex (MC) bus drivers + obj-$(CONFIG_FSL_MC_BUS) += bus/ +--- a/drivers/staging/fsl-mc/TODO ++++ /dev/null +@@ -1,18 +0,0 @@ +-* Add at least one device driver for a DPAA2 object (child device of the +- fsl-mc bus). Most likely candidate for this is adding DPAA2 Ethernet +- driver support, which depends on drivers for several objects: DPNI, +- DPIO, DPMAC. Other pre-requisites include: +- +- * MC firmware uprev. The MC firmware upon which the fsl-mc +- bus driver and DPAA2 object drivers are based is continuing +- to evolve, so minor updates are needed to keep in sync with binary +- interface changes to the MC. +- +-* Cleanup +- +-Please send any patches to Greg Kroah-Hartman <gregkh@linuxfoundation.org>, +-german.rivera@freescale.com, devel@driverdev.osuosl.org, +-linux-kernel@vger.kernel.org +- +-[1] https://lkml.org/lkml/2015/7/9/93 +-[2] https://lkml.org/lkml/2015/7/7/712 +--- a/drivers/staging/fsl-mc/bus/Kconfig ++++ b/drivers/staging/fsl-mc/bus/Kconfig +@@ -1,25 +1,22 @@ ++# SPDX-License-Identifier: GPL-2.0 + # +-# Freescale Management Complex (MC) bus drivers ++# DPAA2 fsl-mc bus + # +-# Copyright (C) 2014 Freescale Semiconductor, Inc. ++# Copyright (C) 2014-2016 Freescale Semiconductor, Inc. + # +-# This file is released under the GPLv2 +-# +- +-config FSL_MC_BUS +- bool "Freescale Management Complex (MC) bus driver" +- depends on OF && ARM64 +- select GENERIC_MSI_IRQ_DOMAIN +- help +- Driver to enable the bus infrastructure for the Freescale +- QorIQ Management Complex (fsl-mc). The fsl-mc is a hardware +- module of the QorIQ LS2 SoCs, that does resource management +- for hardware building-blocks in the SoC that can be used +- to dynamically create networking hardware objects such as +- network interfaces (NICs), crypto accelerator instances, +- or L2 switches. +- +- Only enable this option when building the kernel for +- Freescale QorQIQ LS2xxxx SoCs. + ++config FSL_MC_DPIO ++ tristate "QorIQ DPAA2 DPIO driver" ++ depends on FSL_MC_BUS ++ help ++ Driver for the DPAA2 DPIO object. A DPIO provides queue and ++ buffer management facilities for software to interact with ++ other DPAA2 objects. This driver does not expose the DPIO ++ objects individually, but groups them under a service layer ++ API. + ++config FSL_QBMAN_DEBUG ++ tristate "Freescale QBMAN Debug APIs" ++ depends on FSL_MC_DPIO ++ help ++ QBMan debug assistant APIs. +--- a/drivers/staging/fsl-mc/bus/Makefile ++++ b/drivers/staging/fsl-mc/bus/Makefile +@@ -1,20 +1,9 @@ ++# SPDX-License-Identifier: GPL-2.0 + # + # Freescale Management Complex (MC) bus drivers + # + # Copyright (C) 2014 Freescale Semiconductor, Inc. + # +-# This file is released under the GPLv2 +-# +-obj-$(CONFIG_FSL_MC_BUS) += mc-bus-driver.o - /** +-mc-bus-driver-objs := fsl-mc-bus.o \ +- mc-sys.o \ +- mc-io.o \ +- dprc.o \ +- dpmng.o \ +- dprc-driver.o \ +- fsl-mc-allocator.o \ +- fsl-mc-msi.o \ +- irq-gic-v3-its-fsl-mc-msi.o \ +- dpmcp.o \ +- dpbp.o ++# MC DPIO driver ++obj-$(CONFIG_FSL_MC_DPIO) += dpio/ +--- a/drivers/staging/fsl-mc/bus/dpbp.c ++++ /dev/null +@@ -1,691 +0,0 @@ +-/* Copyright 2013-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 the above-listed copyright holders nor the +- * names of any contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +- * POSSIBILITY OF SUCH DAMAGE. +- */ +-#include "../include/mc-sys.h" +-#include "../include/mc-cmd.h" +-#include "../include/dpbp.h" +-#include "../include/dpbp-cmd.h" +- +-/** +- * dpbp_open() - Open a control session for the specified object. +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @dpbp_id: DPBP unique ID +- * @token: Returned token; use in subsequent API calls +- * +- * This function can be used to open a control session for an +- * already created object; an object may have been declared in +- * the DPL or by calling the dpbp_create function. +- * This function returns a unique authentication token, +- * associated with the specific object ID and the specific MC +- * portal; this token must be used in all subsequent commands for +- * this specific object +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dpbp_open(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- int dpbp_id, +- u16 *token) +-{ +- struct mc_command cmd = { 0 }; +- struct dpbp_cmd_open *cmd_params; +- int err; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN, +- cmd_flags, 0); +- cmd_params = (struct dpbp_cmd_open *)cmd.params; +- cmd_params->dpbp_id = cpu_to_le32(dpbp_id); +- +- /* send command to mc*/ +- err = mc_send_command(mc_io, &cmd); +- if (err) +- return err; +- +- /* retrieve response parameters */ +- *token = mc_cmd_hdr_read_token(&cmd); +- +- return err; +-} +-EXPORT_SYMBOL(dpbp_open); +- +-/** +- * dpbp_close() - Close the control session of the object +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPBP object +- * +- * After this function is called, no further operations are +- * allowed on the object without opening a new control session. +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dpbp_close(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token) +-{ +- struct mc_command cmd = { 0 }; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, cmd_flags, +- token); +- +- /* send command to mc*/ +- return mc_send_command(mc_io, &cmd); +-} +-EXPORT_SYMBOL(dpbp_close); +- +-/** - * dpbp_create() - Create the DPBP object. - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' @@ -346,21 +9664,105 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> -} - -/** - * dpbp_enable() - Enable the DPBP. - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -@@ -250,6 +183,7 @@ int dpbp_is_enabled(struct fsl_mc_io *mc - - return 0; - } -+EXPORT_SYMBOL(dpbp_is_enabled); - - /** - * dpbp_reset() - Reset the DPBP, returns the object to initial state. -@@ -272,310 +206,7 @@ int dpbp_reset(struct fsl_mc_io *mc_io, - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); - } +- * dpbp_enable() - Enable the DPBP. +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPBP object +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dpbp_enable(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token) +-{ +- struct mc_command cmd = { 0 }; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, cmd_flags, +- token); +- +- /* send command to mc*/ +- return mc_send_command(mc_io, &cmd); +-} +-EXPORT_SYMBOL(dpbp_enable); +- +-/** +- * dpbp_disable() - Disable the DPBP. +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPBP object +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dpbp_disable(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token) +-{ +- struct mc_command cmd = { 0 }; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE, +- cmd_flags, token); +- +- /* send command to mc*/ +- return mc_send_command(mc_io, &cmd); +-} +-EXPORT_SYMBOL(dpbp_disable); +- +-/** +- * dpbp_is_enabled() - Check if the DPBP is enabled. +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPBP object +- * @en: Returns '1' if object is enabled; '0' otherwise +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dpbp_is_enabled(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token, +- int *en) +-{ +- struct mc_command cmd = { 0 }; +- struct dpbp_rsp_is_enabled *rsp_params; +- int err; +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPBP_CMDID_IS_ENABLED, cmd_flags, +- token); +- +- /* send command to mc*/ +- err = mc_send_command(mc_io, &cmd); +- if (err) +- return err; +- +- /* retrieve response parameters */ +- rsp_params = (struct dpbp_rsp_is_enabled *)cmd.params; +- *en = rsp_params->enabled & DPBP_ENABLE; +- +- return 0; +-} +- +-/** +- * dpbp_reset() - Reset the DPBP, returns the object to initial state. +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPBP object +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dpbp_reset(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token) +-{ +- struct mc_command cmd = { 0 }; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET, +- cmd_flags, token); +- +- /* send command to mc*/ +- return mc_send_command(mc_io, &cmd); +-} - -/** - * dpbp_set_irq() - Set IRQ information for the DPBP to trigger an interrupt. @@ -665,44 +10067,61 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} -+EXPORT_SYMBOL(dpbp_reset); - - /** - * dpbp_get_attributes - Retrieve DPBP attributes. -@@ -609,83 +240,40 @@ int dpbp_get_attributes(struct fsl_mc_io - rsp_params = (struct dpbp_rsp_get_attributes *)cmd.params; - attr->bpid = le16_to_cpu(rsp_params->bpid); - attr->id = le32_to_cpu(rsp_params->id); +- +-/** +- * dpbp_get_attributes - Retrieve DPBP attributes. +- * +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPBP object +- * @attr: Returned object's attributes +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dpbp_get_attributes(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token, +- struct dpbp_attr *attr) +-{ +- struct mc_command cmd = { 0 }; +- struct dpbp_rsp_get_attributes *rsp_params; +- int err; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_ATTR, +- cmd_flags, token); +- +- /* send command to mc*/ +- err = mc_send_command(mc_io, &cmd); +- if (err) +- return err; +- +- /* retrieve response parameters */ +- rsp_params = (struct dpbp_rsp_get_attributes *)cmd.params; +- attr->bpid = le16_to_cpu(rsp_params->bpid); +- attr->id = le32_to_cpu(rsp_params->id); - attr->version.major = le16_to_cpu(rsp_params->version_major); - attr->version.minor = le16_to_cpu(rsp_params->version_minor); - - return 0; - } - EXPORT_SYMBOL(dpbp_get_attributes); - - /** +- +- return 0; +-} +-EXPORT_SYMBOL(dpbp_get_attributes); +- +-/** - * dpbp_set_notifications() - Set notifications towards software - * @mc_io: Pointer to MC portal's I/O object -+ * dpbp_get_api_version - Get Data Path Buffer Pool API version -+ * @mc_io: Pointer to Mc portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPBP object - * @cfg: notifications configuration -+ * @major_ver: Major version of Buffer Pool API -+ * @minor_ver: Minor version of Buffer Pool API - * - * Return: '0' on Success; Error code otherwise. - */ +- * +- * Return: '0' on Success; Error code otherwise. +- */ -int dpbp_set_notifications(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - struct dpbp_notification_cfg *cfg) -+int dpbp_get_api_version(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 *major_ver, -+ u16 *minor_ver) - { - struct mc_command cmd = { 0 }; +-{ +- struct mc_command cmd = { 0 }; - struct dpbp_cmd_set_notifications *cmd_params; - - /* prepare command */ @@ -737,22 +10156,19 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> -{ - struct mc_command cmd = { 0 }; - struct dpbp_rsp_get_notifications *rsp_params; - int err; - - /* prepare command */ +- int err; +- +- /* prepare command */ - cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_NOTIFICATIONS, - cmd_flags, - token); -+ cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_API_VERSION, -+ cmd_flags, 0); - +- - /* send command to mc*/ -+ /* send command to mc */ - err = mc_send_command(mc_io, &cmd); - if (err) - return err; - - /* retrieve response parameters */ +- err = mc_send_command(mc_io, &cmd); +- if (err) +- return err; +- +- /* retrieve response parameters */ - rsp_params = (struct dpbp_rsp_get_notifications *)cmd.params; - cfg->depletion_entry = le32_to_cpu(rsp_params->depletion_entry); - cfg->depletion_exit = le32_to_cpu(rsp_params->depletion_exit); @@ -761,532 +10177,28 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - cfg->options = le16_to_cpu(rsp_params->options); - cfg->message_ctx = le64_to_cpu(rsp_params->message_ctx); - cfg->message_iova = le64_to_cpu(rsp_params->message_iova); -+ mc_cmd_read_api_version(&cmd, major_ver, minor_ver); - - return 0; - } -+EXPORT_SYMBOL(dpbp_get_api_version); ---- /dev/null -+++ b/drivers/staging/fsl-mc/bus/dpcon-cmd.h -@@ -0,0 +1,85 @@ -+/* -+ * Copyright 2013-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 the above-listed copyright holders nor the -+ * names of any contributors may be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") as published by the Free Software -+ * Foundation, either version 2 of that License or (at your option) any -+ * later version. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. -+ */ -+#ifndef _FSL_DPCON_CMD_H -+#define _FSL_DPCON_CMD_H -+ -+/* DPCON Version */ -+#define DPCON_VER_MAJOR 3 -+#define DPCON_VER_MINOR 2 -+ -+/* Command versioning */ -+#define DPCON_CMD_BASE_VERSION 1 -+#define DPCON_CMD_ID_OFFSET 4 -+ -+#define DPCON_CMD(id) (((id) << DPCON_CMD_ID_OFFSET) | DPCON_CMD_BASE_VERSION) -+ -+/* Command IDs */ -+#define DPCON_CMDID_CLOSE DPCON_CMD(0x800) -+#define DPCON_CMDID_OPEN DPCON_CMD(0x808) -+#define DPCON_CMDID_GET_API_VERSION DPCON_CMD(0xa08) -+ -+#define DPCON_CMDID_ENABLE DPCON_CMD(0x002) -+#define DPCON_CMDID_DISABLE DPCON_CMD(0x003) -+#define DPCON_CMDID_GET_ATTR DPCON_CMD(0x004) -+#define DPCON_CMDID_RESET DPCON_CMD(0x005) -+#define DPCON_CMDID_IS_ENABLED DPCON_CMD(0x006) -+ -+#define DPCON_CMDID_SET_NOTIFICATION DPCON_CMD(0x100) -+ -+struct dpcon_cmd_open { -+ __le32 dpcon_id; -+}; -+ -+#define DPCON_ENABLE 1 -+ -+struct dpcon_rsp_is_enabled { -+ u8 enabled; -+}; -+ -+struct dpcon_rsp_get_attr { -+ /* response word 0 */ -+ __le32 id; -+ __le16 qbman_ch_id; -+ u8 num_priorities; -+ u8 pad; -+}; -+ -+struct dpcon_cmd_set_notification { -+ /* cmd word 0 */ -+ __le32 dpio_id; -+ u8 priority; -+ u8 pad[3]; -+ /* cmd word 1 */ -+ __le64 user_ctx; -+}; -+ -+#endif /* _FSL_DPCON_CMD_H */ ---- /dev/null -+++ b/drivers/staging/fsl-mc/bus/dpcon.c -@@ -0,0 +1,317 @@ -+/* Copyright 2013-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 the above-listed copyright holders nor the -+ * names of any contributors may be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") as published by the Free Software -+ * Foundation, either version 2 of that License or (at your option) any -+ * later version. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. -+ */ -+#include "../include/mc-sys.h" -+#include "../include/mc-cmd.h" -+#include "../include/dpcon.h" -+ -+#include "dpcon-cmd.h" -+ -+/** -+ * dpcon_open() - Open a control session for the specified object -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @dpcon_id: DPCON unique ID -+ * @token: Returned token; use in subsequent API calls -+ * -+ * This function can be used to open a control session for an -+ * already created object; an object may have been declared in -+ * the DPL or by calling the dpcon_create() function. -+ * This function returns a unique authentication token, -+ * associated with the specific object ID and the specific MC -+ * portal; this token must be used in all subsequent commands for -+ * this specific object. -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpcon_open(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ int dpcon_id, -+ u16 *token) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpcon_cmd_open *dpcon_cmd; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPCON_CMDID_OPEN, -+ cmd_flags, -+ 0); -+ dpcon_cmd = (struct dpcon_cmd_open *)cmd.params; -+ dpcon_cmd->dpcon_id = cpu_to_le32(dpcon_id); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ *token = mc_cmd_hdr_read_token(&cmd); -+ -+ return 0; -+} -+EXPORT_SYMBOL(dpcon_open); -+ -+/** -+ * dpcon_close() - Close the control session of the object -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPCON object -+ * -+ * After this function is called, no further operations are -+ * allowed on the object without opening a new control session. -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpcon_close(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token) -+{ -+ struct mc_command cmd = { 0 }; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPCON_CMDID_CLOSE, -+ cmd_flags, -+ token); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+EXPORT_SYMBOL(dpcon_close); -+ -+/** -+ * dpcon_enable() - Enable the DPCON -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPCON object -+ * -+ * Return: '0' on Success; Error code otherwise -+ */ -+int dpcon_enable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token) -+{ -+ struct mc_command cmd = { 0 }; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPCON_CMDID_ENABLE, -+ cmd_flags, -+ token); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+EXPORT_SYMBOL(dpcon_enable); -+ -+/** -+ * dpcon_disable() - Disable the DPCON -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPCON object -+ * -+ * Return: '0' on Success; Error code otherwise -+ */ -+int dpcon_disable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token) -+{ -+ struct mc_command cmd = { 0 }; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPCON_CMDID_DISABLE, -+ cmd_flags, -+ token); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+EXPORT_SYMBOL(dpcon_disable); -+ -+/** -+ * dpcon_is_enabled() - Check if the DPCON is enabled. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPCON object -+ * @en: Returns '1' if object is enabled; '0' otherwise -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpcon_is_enabled(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ int *en) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpcon_rsp_is_enabled *dpcon_rsp; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPCON_CMDID_IS_ENABLED, -+ cmd_flags, -+ token); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ dpcon_rsp = (struct dpcon_rsp_is_enabled *)cmd.params; -+ *en = dpcon_rsp->enabled & DPCON_ENABLE; -+ -+ return 0; -+} -+EXPORT_SYMBOL(dpcon_is_enabled); -+ -+/** -+ * dpcon_reset() - Reset the DPCON, returns the object to initial state. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPCON object -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpcon_reset(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token) -+{ -+ struct mc_command cmd = { 0 }; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPCON_CMDID_RESET, -+ cmd_flags, token); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+EXPORT_SYMBOL(dpcon_reset); -+ -+/** -+ * dpcon_get_attributes() - Retrieve DPCON attributes. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPCON object -+ * @attr: Object's attributes -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpcon_get_attributes(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ struct dpcon_attr *attr) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpcon_rsp_get_attr *dpcon_rsp; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_ATTR, -+ cmd_flags, -+ token); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ dpcon_rsp = (struct dpcon_rsp_get_attr *)cmd.params; -+ attr->id = le32_to_cpu(dpcon_rsp->id); -+ attr->qbman_ch_id = le16_to_cpu(dpcon_rsp->qbman_ch_id); -+ attr->num_priorities = dpcon_rsp->num_priorities; -+ -+ return 0; -+} -+EXPORT_SYMBOL(dpcon_get_attributes); -+ -+/** -+ * dpcon_set_notification() - Set DPCON notification destination -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPCON object -+ * @cfg: Notification parameters -+ * -+ * Return: '0' on Success; Error code otherwise -+ */ -+int dpcon_set_notification(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ struct dpcon_notification_cfg *cfg) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpcon_cmd_set_notification *dpcon_cmd; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPCON_CMDID_SET_NOTIFICATION, -+ cmd_flags, -+ token); -+ dpcon_cmd = (struct dpcon_cmd_set_notification *)cmd.params; -+ dpcon_cmd->dpio_id = cpu_to_le32(cfg->dpio_id); -+ dpcon_cmd->priority = cfg->priority; -+ dpcon_cmd->user_ctx = cpu_to_le64(cfg->user_ctx); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+EXPORT_SYMBOL(dpcon_set_notification); -+ -+/** -+ * dpcon_get_api_version - Get Data Path Concentrator API version -+ * @mc_io: Pointer to MC portal's DPCON object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @major_ver: Major version of DPCON API -+ * @minor_ver: Minor version of DPCON API -+ * -+ * Return: '0' on Success; Error code otherwise -+ */ -+int dpcon_get_api_version(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 *major_ver, -+ u16 *minor_ver) -+{ -+ struct mc_command cmd = { 0 }; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_API_VERSION, -+ cmd_flags, 0); -+ -+ /* send command to mc */ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ mc_cmd_read_api_version(&cmd, major_ver, minor_ver); -+ -+ return 0; -+} -+EXPORT_SYMBOL(dpcon_get_api_version); +- +- return 0; +-} --- /dev/null +++ b/drivers/staging/fsl-mc/bus/dpio/Makefile -@@ -0,0 +1,11 @@ +@@ -0,0 +1,8 @@ ++# SPDX-License-Identifier: GPL-2.0 +# +# QorIQ DPAA2 DPIO driver +# + -+subdir-ccflags-y := -Werror -+ +obj-$(CONFIG_FSL_MC_DPIO) += fsl-mc-dpio.o + +fsl-mc-dpio-objs := dpio.o qbman-portal.o dpio-service.o dpio-driver.o -+ -+obj-$(CONFIG_FSL_QBMAN_DEBUG) += qbman_debug.o ---- a/drivers/staging/fsl-mc/include/dpcon-cmd.h -+++ /dev/null -@@ -1,62 +0,0 @@ --/* Copyright 2013-2015 Freescale Semiconductor Inc. -- * -- * Redistribution and use in source and binary forms, with or without -- * modification, are permitted provided that the following conditions are met: -- * * Redistributions of source code must retain the above copyright -- * notice, this list of conditions and the following disclaimer. -- * * Redistributions in binary form must reproduce the above copyright -- * notice, this list of conditions and the following disclaimer in the -- * documentation and/or other materials provided with the distribution. -- * * Neither the name of the above-listed copyright holders nor the -- * names of any contributors may be used to endorse or promote products -- * derived from this software without specific prior written permission. -- * -- * -- * ALTERNATIVELY, this software may be distributed under the terms of the -- * GNU General Public License ("GPL") as published by the Free Software -- * Foundation, either version 2 of that License or (at your option) any -- * later version. -- * -- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -- * POSSIBILITY OF SUCH DAMAGE. -- */ --#ifndef _FSL_DPCON_CMD_H --#define _FSL_DPCON_CMD_H -- --/* DPCON Version */ --#define DPCON_VER_MAJOR 2 --#define DPCON_VER_MINOR 1 -- --/* Command IDs */ --#define DPCON_CMDID_CLOSE 0x800 --#define DPCON_CMDID_OPEN 0x808 --#define DPCON_CMDID_CREATE 0x908 --#define DPCON_CMDID_DESTROY 0x900 -- --#define DPCON_CMDID_ENABLE 0x002 --#define DPCON_CMDID_DISABLE 0x003 --#define DPCON_CMDID_GET_ATTR 0x004 --#define DPCON_CMDID_RESET 0x005 --#define DPCON_CMDID_IS_ENABLED 0x006 -- --#define DPCON_CMDID_SET_IRQ 0x010 --#define DPCON_CMDID_GET_IRQ 0x011 --#define DPCON_CMDID_SET_IRQ_ENABLE 0x012 --#define DPCON_CMDID_GET_IRQ_ENABLE 0x013 --#define DPCON_CMDID_SET_IRQ_MASK 0x014 --#define DPCON_CMDID_GET_IRQ_MASK 0x015 --#define DPCON_CMDID_GET_IRQ_STATUS 0x016 --#define DPCON_CMDID_CLEAR_IRQ_STATUS 0x017 -- --#define DPCON_CMDID_SET_NOTIFICATION 0x100 -- --#endif /* _FSL_DPCON_CMD_H */ --- /dev/null +++ b/drivers/staging/fsl-mc/bus/dpio/dpio-cmd.h -@@ -0,0 +1,75 @@ +@@ -0,0 +1,50 @@ ++/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* + * Copyright 2013-2016 Freescale Semiconductor Inc. + * Copyright 2016 NXP + * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are met: -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * * Neither the name of the above-listed copyright holders nor the -+ * names of any contributors may be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") as published by the Free Software -+ * Foundation, either version 2 of that License or (at your option) any -+ * later version. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _FSL_DPIO_CMD_H +#define _FSL_DPIO_CMD_H @@ -1309,6 +10221,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#define DPIO_CMDID_ENABLE DPIO_CMD(0x002) +#define DPIO_CMDID_DISABLE DPIO_CMD(0x003) +#define DPIO_CMDID_GET_ATTR DPIO_CMD(0x004) ++#define DPIO_CMDID_RESET DPIO_CMD(0x005) + +struct dpio_cmd_open { + __le32 dpio_id; @@ -1333,37 +10246,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#endif /* _FSL_DPIO_CMD_H */ --- /dev/null +++ b/drivers/staging/fsl-mc/bus/dpio/dpio-driver.c -@@ -0,0 +1,296 @@ +@@ -0,0 +1,278 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright 2014-2016 Freescale Semiconductor Inc. + * Copyright 2016 NXP + * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are met: -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * * Neither the name of Freescale Semiconductor nor the -+ * names of its contributors may be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") as published by the Free Software -+ * Foundation, either version 2 of that License or (at your option) any -+ * later version. -+ * -+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY -+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY -+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <linux/types.h> @@ -1375,7 +10263,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#include <linux/dma-mapping.h> +#include <linux/delay.h> + -+#include "../../include/mc.h" ++#include <linux/fsl/mc.h> +#include "../../include/dpaa2-io.h" + +#include "qbman-portal.h" @@ -1471,6 +10359,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + goto err_open; + } + ++ err = dpio_reset(dpio_dev->mc_io, 0, dpio_dev->mc_handle); ++ if (err) { ++ dev_err(dev, "dpio_reset() failed\n"); ++ goto err_reset; ++ } ++ + err = dpio_get_attributes(dpio_dev->mc_io, 0, dpio_dev->mc_handle, + &dpio_attrs); + if (err) { @@ -1543,6 +10437,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +err_allocate_irqs: + dpio_disable(dpio_dev->mc_io, 0, dpio_dev->mc_handle); +err_get_attr: ++err_reset: + dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle); +err_open: + fsl_mc_portal_free(dpio_dev->mc_io); @@ -1632,40 +10527,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +module_exit(dpio_driver_exit); --- /dev/null +++ b/drivers/staging/fsl-mc/bus/dpio/dpio-service.c -@@ -0,0 +1,693 @@ +@@ -0,0 +1,780 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright 2014-2016 Freescale Semiconductor Inc. + * Copyright 2016 NXP + * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are met: -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * * Neither the name of Freescale Semiconductor nor the -+ * names of its contributors may be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") as published by the Free Software -+ * Foundation, either version 2 of that License or (at your option) any -+ * later version. -+ * -+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY -+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY -+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include <linux/types.h> -+#include "../../include/mc.h" ++#include <linux/fsl/mc.h> +#include "../../include/dpaa2-io.h" +#include <linux/init.h> +#include <linux/module.h> @@ -1676,10 +10546,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +#include "dpio.h" +#include "qbman-portal.h" -+#include "qbman_debug.h" + +struct dpaa2_io { -+ atomic_t refs; + struct dpaa2_io_desc dpio_desc; + struct qbman_swp_desc swp_desc; + struct qbman_swp *swp; @@ -1712,7 +10580,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + if (d) + return d; + -+ if (unlikely(cpu >= (int)num_possible_cpus())) ++ if (cpu != DPAA2_IO_ANY_CPU && cpu >= num_possible_cpus()) + return NULL; + + /* @@ -1745,6 +10613,23 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +} + +/** ++ * dpaa2_io_service_select() - return a dpaa2_io service affined to this cpu ++ * @cpu: the cpu id ++ * ++ * Return the affine dpaa2_io service, or NULL if there is no service affined ++ * to the specified cpu. If DPAA2_IO_ANY_CPU is used, return the next available ++ * service. ++ */ ++struct dpaa2_io *dpaa2_io_service_select(int cpu) ++{ ++ if (cpu == DPAA2_IO_ANY_CPU) ++ return service_select(NULL); ++ ++ return service_select_by_cpu(NULL, cpu); ++} ++EXPORT_SYMBOL_GPL(dpaa2_io_service_select); ++ ++/** + * dpaa2_io_create() - create a dpaa2_io object. + * @desc: the dpaa2_io descriptor + * @@ -1761,12 +10646,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return NULL; + + /* check if CPU is out of range (-1 means any cpu) */ -+ if (desc->cpu >= (int)num_possible_cpus()) { ++ if (desc->cpu != DPAA2_IO_ANY_CPU && desc->cpu >= num_possible_cpus()) { + kfree(obj); + return NULL; + } + -+ atomic_set(&obj->refs, 1); + obj->dpio_desc = *desc; + obj->swp_desc.cena_bar = obj->dpio_desc.regs_cena; + obj->swp_desc.cinh_bar = obj->dpio_desc.regs_cinh; @@ -1798,7 +10682,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + return obj; +} -+EXPORT_SYMBOL(dpaa2_io_create); + +/** + * dpaa2_io_down() - release the dpaa2_io object. @@ -1811,11 +10694,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + */ +void dpaa2_io_down(struct dpaa2_io *d) +{ -+ if (!atomic_dec_and_test(&d->refs)) -+ return; + kfree(d); +} -+EXPORT_SYMBOL(dpaa2_io_down); + +#define DPAA_POLL_MAX 32 + @@ -1846,7 +10726,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u64 q64; + + q64 = qbman_result_SCN_ctx(dq); -+ ctx = (void *)q64; ++ ctx = (void *)(uintptr_t)q64; + ctx->cb(ctx); + } else { + pr_crit("fsl-mc-dpio: Unrecognised/ignored DQRR entry\n"); @@ -1862,7 +10742,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + qbman_swp_interrupt_set_inhibit(swp, 0); + return IRQ_HANDLED; +} -+EXPORT_SYMBOL(dpaa2_io_irq); + +/** + * dpaa2_io_service_register() - Prepare for servicing of FQDAN or CDAN @@ -1892,7 +10771,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return -ENODEV; + + ctx->dpio_id = d->dpio_desc.dpio_id; -+ ctx->qman64 = (u64)ctx; ++ ctx->qman64 = (u64)(uintptr_t)ctx; + ctx->dpio_private = d; + spin_lock_irqsave(&d->lock_notifications, irqflags); + list_add(&ctx->node, &d->notifications); @@ -1900,12 +10779,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + /* Enable the generation of CDAN notifications */ + if (ctx->is_cdan) -+ qbman_swp_CDAN_set_context_enable(d->swp, -+ (u16)ctx->id, -+ ctx->qman64); ++ return qbman_swp_CDAN_set_context_enable(d->swp, ++ (u16)ctx->id, ++ ctx->qman64); + return 0; +} -+EXPORT_SYMBOL(dpaa2_io_service_register); ++EXPORT_SYMBOL_GPL(dpaa2_io_service_register); + +/** + * dpaa2_io_service_deregister - The opposite of 'register'. @@ -1928,7 +10807,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + list_del(&ctx->node); + spin_unlock_irqrestore(&d->lock_notifications, irqflags); +} -+EXPORT_SYMBOL(dpaa2_io_service_deregister); ++EXPORT_SYMBOL_GPL(dpaa2_io_service_deregister); + +/** + * dpaa2_io_service_rearm() - Rearm the notification for the given DPIO service. @@ -1962,7 +10841,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + return err; +} -+EXPORT_SYMBOL(dpaa2_io_service_rearm); ++EXPORT_SYMBOL_GPL(dpaa2_io_service_rearm); + +/** + * dpaa2_io_service_pull_fq() - pull dequeue functions from a fq. @@ -2025,7 +10904,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + return err; +} -+EXPORT_SYMBOL(dpaa2_io_service_pull_channel); ++EXPORT_SYMBOL_GPL(dpaa2_io_service_pull_channel); + +/** + * dpaa2_io_service_enqueue_fq() - Enqueue a frame to a frame queue. @@ -2081,7 +10960,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + return qbman_swp_enqueue(d->swp, &ed, fd); +} -+EXPORT_SYMBOL(dpaa2_io_service_enqueue_qd); ++EXPORT_SYMBOL_GPL(dpaa2_io_service_enqueue_qd); + +/** + * dpaa2_io_service_release() - Release buffers to a buffer pool. @@ -2108,7 +10987,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + return qbman_swp_release(d->swp, &rd, buffers, num_buffers); +} -+EXPORT_SYMBOL(dpaa2_io_service_release); ++EXPORT_SYMBOL_GPL(dpaa2_io_service_release); + +/** + * dpaa2_io_service_acquire() - Acquire buffers from a buffer pool. @@ -2139,7 +11018,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + return err; +} -+EXPORT_SYMBOL(dpaa2_io_service_acquire); ++EXPORT_SYMBOL_GPL(dpaa2_io_service_acquire); + +/* + * 'Stores' are reusable memory blocks for holding dequeue results, and to @@ -2193,7 +11072,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + return ret; +} -+EXPORT_SYMBOL(dpaa2_io_store_create); ++EXPORT_SYMBOL_GPL(dpaa2_io_store_create); + +/** + * dpaa2_io_store_destroy() - Frees the dma memory storage for dequeue @@ -2207,7 +11086,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + kfree(s->alloced_addr); + kfree(s); +} -+EXPORT_SYMBOL(dpaa2_io_store_destroy); ++EXPORT_SYMBOL_GPL(dpaa2_io_store_destroy); + +/** + * dpaa2_io_store_next() - Determine when the next dequeue result is available. @@ -2255,9 +11134,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + return ret; +} -+EXPORT_SYMBOL(dpaa2_io_store_next); ++EXPORT_SYMBOL_GPL(dpaa2_io_store_next); + -+#ifdef CONFIG_FSL_QBMAN_DEBUG +/** + * dpaa2_io_query_fq_count() - Get the frame and byte count for a given fq. + * @d: the given DPIO object. @@ -2270,10 +11148,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * + * Return 0 for a successful query, and negative error code if query fails. + */ -+int dpaa2_io_query_fq_count(struct dpaa2_io *d, uint32_t fqid, ++int dpaa2_io_query_fq_count(struct dpaa2_io *d, u32 fqid, + u32 *fcnt, u32 *bcnt) +{ -+ struct qbman_attr state; ++ struct qbman_fq_query_np_rslt state; + struct qbman_swp *swp; + unsigned long irqflags; + int ret; @@ -2296,17 +11174,17 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +EXPORT_SYMBOL(dpaa2_io_query_fq_count); + +/** -+ * dpaa2_io_query_bp_count() - Query the number of buffers currenty in a ++ * dpaa2_io_query_bp_count() - Query the number of buffers currently in a + * buffer pool. + * @d: the given DPIO object. + * @bpid: the index of buffer pool to be queried. + * @num: the queried number of buffers in the buffer pool. + * -+ * Return 0 for a sucessful query, and negative error code if query fails. ++ * Return 0 for a successful query, and negative error code if query fails. + */ -+int dpaa2_io_query_bp_count(struct dpaa2_io *d, uint32_t bpid, u32 *num) ++int dpaa2_io_query_bp_count(struct dpaa2_io *d, u32 bpid, u32 *num) +{ -+ struct qbman_attr state; ++ struct qbman_bp_query_rslt state; + struct qbman_swp *swp; + unsigned long irqflags; + int ret; @@ -2325,44 +11203,122 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return 0; +} +EXPORT_SYMBOL(dpaa2_io_query_bp_count); -+#endif ++ ++/** ++ * dpaa2_io_service_enqueue_orp_fq() - Enqueue a frame to a frame queue with ++ * order restoration ++ * @d: the given DPIO service. ++ * @fqid: the given frame queue id. ++ * @fd: the frame descriptor which is enqueued. ++ * @orpid: the order restoration point ID ++ * @seqnum: the order sequence number ++ * @last: must be set for the final frame if seqnum is shared (spilt frame) ++ * ++ * Performs an enqueue to a frame queue using the specified order restoration ++ * point. The QMan device will ensure the order of frames placed on the ++ * queue will be ordered as per the sequence number. ++ * ++ * In the case a frame is split it is possible to enqueue using the same ++ * sequence number more than once. The final frame in a shared sequence number ++ * most be indicated by setting last = 1. For non shared sequence numbers ++ * last = 1 must always be set. ++ * ++ * Return 0 for successful enqueue, or -EBUSY if the enqueue ring is not ready, ++ * or -ENODEV if there is no dpio service. ++ */ ++int dpaa2_io_service_enqueue_orp_fq(struct dpaa2_io *d, u32 fqid, ++ const struct dpaa2_fd *fd, u16 orpid, ++ u16 seqnum, int last) ++{ ++ struct qbman_eq_desc ed; ++ ++ d = service_select(d); ++ if (!d) ++ return -ENODEV; ++ qbman_eq_desc_clear(&ed); ++ qbman_eq_desc_set_orp(&ed, 0, orpid, seqnum, !last); ++ qbman_eq_desc_set_fq(&ed, fqid); ++ return qbman_swp_enqueue(d->swp, &ed, fd); ++} ++EXPORT_SYMBOL(dpaa2_io_service_enqueue_orp_fq); ++ ++/** ++ * dpaa2_io_service_enqueue_orp_qd() - Enqueue a frame to a queueing destination ++ * with order restoration ++ * @d: the given DPIO service. ++ * @qdid: the given queuing destination id. ++ * @fd: the frame descriptor which is enqueued. ++ * @orpid: the order restoration point ID ++ * @seqnum: the order sequence number ++ * @last: must be set for the final frame if seqnum is shared (spilt frame) ++ * ++ * Performs an enqueue to a frame queue using the specified order restoration ++ * point. The QMan device will ensure the order of frames placed on the ++ * queue will be ordered as per the sequence number. ++ * ++ * In the case a frame is split it is possible to enqueue using the same ++ * sequence number more than once. The final frame in a shared sequence number ++ * most be indicated by setting last = 1. For non shared sequence numbers ++ * last = 1 must always be set. ++ * ++ * Return 0 for successful enqueue, or -EBUSY if the enqueue ring is not ready, ++ * or -ENODEV if there is no dpio service. ++ */ ++int dpaa2_io_service_enqueue_orp_qd(struct dpaa2_io *d, u32 qdid, u8 prio, ++ u16 qdbin, const struct dpaa2_fd *fd, ++ u16 orpid, u16 seqnum, int last) ++{ ++ struct qbman_eq_desc ed; ++ ++ d = service_select(d); ++ if (!d) ++ return -ENODEV; ++ qbman_eq_desc_clear(&ed); ++ qbman_eq_desc_set_orp(&ed, 0, orpid, seqnum, !last); ++ qbman_eq_desc_set_qd(&ed, qdid, qdbin, prio); ++ return qbman_swp_enqueue(d->swp, &ed, fd); ++} ++EXPORT_SYMBOL_GPL(dpaa2_io_service_enqueue_orp_qd); ++ ++/** ++ * dpaa2_io_service_orp_seqnum_drop() - Remove a sequence number from ++ * an order restoration list ++ * @d: the given DPIO service. ++ * @orpid: Order restoration point to remove a sequence number from ++ * @seqnum: Sequence number to remove ++ * ++ * Removes a frames sequence number from an order restoration point without ++ * enqueing the frame. Used to indicate that the order restoration hardware ++ * should not expect to see this sequence number. Typically used to indicate ++ * a frame was terminated or dropped from a flow. ++ * ++ * Return 0 for successful enqueue, or -EBUSY if the enqueue ring is not ready, ++ * or -ENODEV if there is no dpio service. ++ */ ++int dpaa2_io_service_orp_seqnum_drop(struct dpaa2_io *d, u16 orpid, u16 seqnum) ++{ ++ struct qbman_eq_desc ed; ++ struct dpaa2_fd fd; ++ ++ d = service_select(d); ++ if (!d) ++ return -ENODEV; ++ qbman_eq_desc_clear(&ed); ++ qbman_eq_desc_set_orp_hole(&ed, orpid, seqnum); ++ return qbman_swp_enqueue(d->swp, &ed, &fd); ++} ++EXPORT_SYMBOL_GPL(dpaa2_io_service_orp_seqnum_drop); --- /dev/null +++ b/drivers/staging/fsl-mc/bus/dpio/dpio.c -@@ -0,0 +1,224 @@ +@@ -0,0 +1,221 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright 2013-2016 Freescale Semiconductor Inc. + * Copyright 2016 NXP + * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are met: -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * * Neither the name of the above-listed copyright holders nor the -+ * names of any contributors may be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") as published by the Free Software -+ * Foundation, either version 2 of that License or (at your option) any -+ * later version. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. + */ -+#include "../../include/mc-sys.h" -+#include "../../include/mc-cmd.h" ++#include <linux/kernel.h> ++#include <linux/fsl/mc.h> + +#include "dpio.h" +#include "dpio-cmd.h" @@ -2394,7 +11350,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + int dpio_id, + u16 *token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpio_cmd_open *dpio_cmd; + int err; + @@ -2427,7 +11383,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u16 token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPIO_CMDID_CLOSE, @@ -2449,7 +11405,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u16 token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPIO_CMDID_ENABLE, @@ -2471,7 +11427,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u16 token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPIO_CMDID_DISABLE, @@ -2495,7 +11451,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + struct dpio_attr *attr) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpio_rsp_get_attr *dpio_rsp; + int err; + @@ -2537,7 +11493,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 *major_ver, + u16 *minor_ver) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ @@ -2553,40 +11509,37 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + return 0; +} ++ ++/** ++ * dpio_reset() - Reset the DPIO, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_reset(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token) ++{ ++ struct fsl_mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} --- /dev/null +++ b/drivers/staging/fsl-mc/bus/dpio/dpio.h -@@ -0,0 +1,109 @@ +@@ -0,0 +1,87 @@ ++/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* + * Copyright 2013-2016 Freescale Semiconductor Inc. + * Copyright 2016 NXP + * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are met: -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * * Neither the name of the above-listed copyright holders nor the -+ * names of any contributors may be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") as published by the Free Software -+ * Foundation, either version 2 of that License or (at your option) any -+ * later version. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __FSL_DPIO_H +#define __FSL_DPIO_H @@ -2664,40 +11617,19 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 *major_ver, + u16 *minor_ver); + ++int dpio_reset(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token); ++ +#endif /* __FSL_DPIO_H */ --- /dev/null +++ b/drivers/staging/fsl-mc/bus/dpio/qbman-portal.c -@@ -0,0 +1,1049 @@ +@@ -0,0 +1,1164 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * -+ * 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 <asm/cacheflush.h> @@ -2707,9 +11639,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +#include "qbman-portal.h" + -+struct qb_attr_code code_generic_verb = QB_CODE(0, 0, 7); -+struct qb_attr_code code_generic_rslt = QB_CODE(0, 8, 8); -+ +#define QMAN_REV_4000 0x04000000 +#define QMAN_REV_4100 0x04010000 +#define QMAN_REV_4101 0x04010001 @@ -2817,18 +11746,18 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 epm, int sd, int sp, int se, + int dp, int de, int ep) +{ -+ return cpu_to_le32 (max_fill << SWP_CFG_DQRR_MF_SHIFT | -+ est << SWP_CFG_EST_SHIFT | -+ wn << SWP_CFG_WN_SHIFT | -+ rpm << SWP_CFG_RPM_SHIFT | -+ dcm << SWP_CFG_DCM_SHIFT | -+ epm << SWP_CFG_EPM_SHIFT | -+ sd << SWP_CFG_SD_SHIFT | -+ sp << SWP_CFG_SP_SHIFT | -+ se << SWP_CFG_SE_SHIFT | -+ dp << SWP_CFG_DP_SHIFT | -+ de << SWP_CFG_DE_SHIFT | -+ ep << SWP_CFG_EP_SHIFT); ++ return (max_fill << SWP_CFG_DQRR_MF_SHIFT | ++ est << SWP_CFG_EST_SHIFT | ++ wn << SWP_CFG_WN_SHIFT | ++ rpm << SWP_CFG_RPM_SHIFT | ++ dcm << SWP_CFG_DCM_SHIFT | ++ epm << SWP_CFG_EPM_SHIFT | ++ sd << SWP_CFG_SD_SHIFT | ++ sp << SWP_CFG_SP_SHIFT | ++ se << SWP_CFG_SE_SHIFT | ++ dp << SWP_CFG_DP_SHIFT | ++ de << SWP_CFG_DE_SHIFT | ++ ep << SWP_CFG_EP_SHIFT); +} + +/** @@ -3053,6 +11982,43 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + d->verb |= enqueue_rejects_to_fq; +} + ++/** ++ * qbman_eq_desc_set_orp() - Set order-restoration in the enqueue descriptor ++ * @d: the enqueue descriptor. ++ * @response_success: 1 = enqueue with response always; 0 = enqueue with ++ * rejections returned on a FQ. ++ * @oprid: the order point record id. ++ * @seqnum: the order restoration sequence number. ++ * @incomplete: indicates whether this is the last fragments using the same ++ * sequence number. ++ */ ++void qbman_eq_desc_set_orp(struct qbman_eq_desc *d, int respond_success, ++ u16 oprid, u16 seqnum, int incomplete) ++{ ++ d->verb |= (1 << QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT); ++ if (respond_success) ++ d->verb |= enqueue_response_always; ++ else ++ d->verb |= enqueue_rejects_to_fq; ++ d->orpid = cpu_to_le16(oprid); ++ d->seqnum = cpu_to_le16((!!incomplete << 14) | seqnum); ++} ++ ++/** ++ * qbman_eq_desc_set_orp_hole() - fill a hole in the order-restoration sequence ++ * without any enqueue ++ * @d: the enqueue descriptor. ++ * @oprid: the order point record id. ++ * @seqnum: the order restoration sequence number. ++ */ ++void qbman_eq_desc_set_orp_hole(struct qbman_eq_desc *d, u16 oprid, ++ u16 seqnum) ++{ ++ d->verb |= (1 << QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT) | enqueue_empty; ++ d->orpid = cpu_to_le16(oprid); ++ d->seqnum = cpu_to_le16(seqnum); ++} ++ +/* + * Exactly one of the following descriptor "targets" should be set. (Calling any + * one of these will replace the effect of any prior call to one of these.) @@ -3112,7 +12078,17 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return -EBUSY; + + p = qbman_get_cmd(s, QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar))); -+ memcpy(&p->dca, &d->dca, 31); ++ /* This is mapped as DEVICE type memory, writes are ++ * with address alignment: ++ * desc.dca address alignment = 1 ++ * desc.seqnum address alignment = 2 ++ * desc.orpid address alignment = 4 ++ * desc.tgtid address alignment = 8 ++ */ ++ p->dca = d->dca; ++ p->seqnum = d->seqnum; ++ p->orpid = d->orpid; ++ memcpy(&p->tgtid, &d->tgtid, 24); + memcpy(&p->fd, fd, sizeof(*fd)); + + /* Set the verb byte, have to substitute in the valid-bit */ @@ -3206,7 +12182,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + int stash) +{ + /* save the virtual address */ -+ d->rsp_addr_virt = (u64)storage; ++ d->rsp_addr_virt = (u64)(uintptr_t)storage; + + if (!storage) { + d->verb &= ~(1 << QB_VDQCR_VERB_RLS_SHIFT); @@ -3299,7 +12275,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + atomic_inc(&s->vdq.available); + return -EBUSY; + } -+ s->vdq.storage = (void *)d->rsp_addr_virt; ++ s->vdq.storage = (void *)(uintptr_t)d->rsp_addr_virt; + p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR); + p->numf = d->numf; + p->tok = QMAN_DQ_TOKEN_VALID; @@ -3539,7 +12515,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +struct qbman_acquire_desc { + u8 verb; + u8 reserved; -+ u16 bpid; ++ __le16 bpid; + u8 num; + u8 reserved2[59]; +}; @@ -3547,10 +12523,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +struct qbman_acquire_rslt { + u8 verb; + u8 rslt; -+ u16 reserved; ++ __le16 reserved; + u8 num; + u8 reserved2[3]; -+ u64 buf[7]; ++ __le64 buf[7]; +}; + +/** @@ -3613,7 +12589,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +struct qbman_alt_fq_state_desc { + u8 verb; + u8 reserved[3]; -+ u32 fqid; ++ __le32 fqid; + u8 reserved2[56]; +}; + @@ -3636,7 +12612,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + if (!p) + return -EBUSY; + -+ p->fqid = cpu_to_le32(fqid) & ALT_FQ_FQID_MASK; ++ p->fqid = cpu_to_le32(fqid & ALT_FQ_FQID_MASK); + + /* Complete the management command */ + r = qbman_swp_mc_complete(s, p, alt_fq_verb); @@ -3662,11 +12638,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +struct qbman_cdan_ctrl_desc { + u8 verb; + u8 reserved; -+ u16 ch; ++ __le16 ch; + u8 we; + u8 ctrl; -+ u16 reserved2; -+ u64 cdan_ctx; ++ __le16 reserved2; ++ __le64 cdan_ctx; + u8 reserved3[48]; + +}; @@ -3674,7 +12650,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +struct qbman_cdan_ctrl_rslt { + u8 verb; + u8 rslt; -+ u16 ch; ++ __le16 ch; + u8 reserved[60]; +}; + @@ -3717,44 +12693,114 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + return 0; +} ++ ++#define QBMAN_RESPONSE_VERB_MASK 0x7f ++#define QBMAN_FQ_QUERY_NP 0x45 ++#define QBMAN_BP_QUERY 0x32 ++ ++struct qbman_fq_query_desc { ++ u8 verb; ++ u8 reserved[3]; ++ u32 fqid; ++ u8 reserved2[56]; ++}; ++ ++int qbman_fq_query_state(struct qbman_swp *s, u32 fqid, ++ struct qbman_fq_query_np_rslt *r) ++{ ++ struct qbman_fq_query_desc *p; ++ void *resp; ++ ++ p = (struct qbman_fq_query_desc *)qbman_swp_mc_start(s); ++ if (!p) ++ return -EBUSY; ++ ++ /* FQID is a 24 bit value */ ++ p->fqid = cpu_to_le32(fqid) & 0x00FFFFFF; ++ resp = qbman_swp_mc_complete(s, p, QBMAN_FQ_QUERY_NP); ++ if (!resp) { ++ pr_err("qbman: Query FQID %d NP fields failed, no response\n", ++ fqid); ++ return -EIO; ++ } ++ *r = *(struct qbman_fq_query_np_rslt *)resp; ++ /* Decode the outcome */ ++ WARN_ON((r->verb & QBMAN_RESPONSE_VERB_MASK) != QBMAN_FQ_QUERY_NP); ++ ++ /* Determine success or failure */ ++ if (r->rslt != QBMAN_MC_RSLT_OK) { ++ pr_err("Query NP fields of FQID 0x%x failed, code=0x%02x\n", ++ p->fqid, r->rslt); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++u32 qbman_fq_state_frame_count(const struct qbman_fq_query_np_rslt *r) ++{ ++ return (r->frm_cnt & 0x00FFFFFF); ++} ++ ++u32 qbman_fq_state_byte_count(const struct qbman_fq_query_np_rslt *r) ++{ ++ return r->byte_cnt; ++} ++ ++struct qbman_bp_query_desc { ++ u8 verb; ++ u8 reserved; ++ u16 bpid; ++ u8 reserved2[60]; ++}; ++ ++int qbman_bp_query(struct qbman_swp *s, u32 bpid, ++ struct qbman_bp_query_rslt *r) ++{ ++ struct qbman_bp_query_desc *p; ++ void *resp; ++ ++ p = (struct qbman_bp_query_desc *)qbman_swp_mc_start(s); ++ if (!p) ++ return -EBUSY; ++ ++ p->bpid = bpid; ++ resp = qbman_swp_mc_complete(s, p, QBMAN_BP_QUERY); ++ if (!resp) { ++ pr_err("qbman: Query BPID %d fields failed, no response\n", ++ bpid); ++ return -EIO; ++ } ++ *r = *(struct qbman_bp_query_rslt *)resp; ++ /* Decode the outcome */ ++ WARN_ON((r->verb & QBMAN_RESPONSE_VERB_MASK) != QBMAN_BP_QUERY); ++ ++ /* Determine success or failure */ ++ if (r->rslt != QBMAN_MC_RSLT_OK) { ++ pr_err("Query fields of BPID 0x%x failed, code=0x%02x\n", ++ bpid, r->rslt); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++u32 qbman_bp_info_num_free_bufs(struct qbman_bp_query_rslt *a) ++{ ++ return a->fill; ++} --- /dev/null +++ b/drivers/staging/fsl-mc/bus/dpio/qbman-portal.h -@@ -0,0 +1,662 @@ +@@ -0,0 +1,505 @@ ++/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* + * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * -+ * 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_QBMAN_PORTAL_H +#define __FSL_QBMAN_PORTAL_H + -+#include "qbman_private.h" +#include "../../include/dpaa2-fd.h" + +struct dpaa2_dq; @@ -3780,8 +12826,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 numf; + u8 tok; + u8 reserved; -+ u32 dq_src; -+ u64 rsp_addr; ++ __le32 dq_src; ++ __le64 rsp_addr; + u64 rsp_addr_virt; + u8 padding[40]; +}; @@ -3818,17 +12864,17 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +struct qbman_eq_desc { + u8 verb; + u8 dca; -+ u16 seqnum; -+ u16 orpid; -+ u16 reserved1; -+ u32 tgtid; -+ u32 tag; -+ u16 qdbin; ++ __le16 seqnum; ++ __le16 orpid; ++ __le16 reserved1; ++ __le32 tgtid; ++ __le32 tag; ++ __le16 qdbin; + u8 qpri; + u8 reserved[3]; + u8 wae; + u8 rspid; -+ u64 rsp_addr; ++ __le64 rsp_addr; + u8 fd[32]; +}; + @@ -3836,9 +12882,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +struct qbman_release_desc { + u8 verb; + u8 reserved; -+ u16 bpid; -+ u32 reserved2; -+ u64 buf[7]; ++ __le16 bpid; ++ __le32 reserved2; ++ __le64 buf[7]; +}; + +/* Management command result codes */ @@ -3910,6 +12956,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +void qbman_eq_desc_clear(struct qbman_eq_desc *d); +void qbman_eq_desc_set_no_orp(struct qbman_eq_desc *d, int respond_success); ++void qbman_eq_desc_set_orp(struct qbman_eq_desc *d, int respond_success, ++ u16 oprid, u16 seqnum, int incomplete); ++void qbman_eq_desc_set_orp_hole(struct qbman_eq_desc *d, u16 oprid, u16 seqnum); +void qbman_eq_desc_set_token(struct qbman_eq_desc *d, u8 token); +void qbman_eq_desc_set_fq(struct qbman_eq_desc *d, u32 fqid); +void qbman_eq_desc_set_qd(struct qbman_eq_desc *d, u32 qdid, @@ -4189,1389 +13238,103 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return cmd; +} + -+/* ------------ */ -+/* qb_attr_code */ -+/* ------------ */ -+ -+/* This struct locates a sub-field within a QBMan portal (CENA) cacheline which -+ * is either serving as a configuration command or a query result. The -+ * representation is inherently little-endian, as the indexing of the words is -+ * itself little-endian in nature and layerscape is little endian for anything -+ * that crosses a word boundary too (64-bit fields are the obvious examples). -+ */ -+struct qb_attr_code { -+ unsigned int word; /* which u32[] array member encodes the field */ -+ unsigned int lsoffset; /* encoding offset from ls-bit */ -+ unsigned int width; /* encoding width. (bool must be 1.) */ -+}; -+ -+/* Some pre-defined codes */ -+extern struct qb_attr_code code_generic_verb; -+extern struct qb_attr_code code_generic_rslt; -+ -+/* Macros to define codes */ -+#define QB_CODE(a, b, c) { a, b, c} -+#define QB_CODE_NULL \ -+ QB_CODE((unsigned int)-1, (unsigned int)-1, (unsigned int)-1) -+ -+/* Rotate a code "ms", meaning that it moves from less-significant bytes to -+ * more-significant, from less-significant words to more-significant, etc. The -+ * "ls" version does the inverse, from more-significant towards -+ * less-significant. -+ */ -+static inline void qb_attr_code_rotate_ms(struct qb_attr_code *code, -+ unsigned int bits) -+{ -+ code->lsoffset += bits; -+ while (code->lsoffset > 31) { -+ code->word++; -+ code->lsoffset -= 32; -+ } -+} -+ -+static inline void qb_attr_code_rotate_ls(struct qb_attr_code *code, -+ unsigned int bits) -+{ -+ /* Don't be fooled, this trick should work because the types are -+ * unsigned. So the case that interests the while loop (the rotate has -+ * gone too far and the word count needs to compensate for it), is -+ * manifested when lsoffset is negative. But that equates to a really -+ * large unsigned value, starting with lots of "F"s. As such, we can -+ * continue adding 32 back to it until it wraps back round above zero, -+ * to a value of 31 or less... -+ */ -+ code->lsoffset -= bits; -+ while (code->lsoffset > 31) { -+ code->word--; -+ code->lsoffset += 32; -+ } -+} -+ -+/* Implement a loop of code rotations until 'expr' evaluates to FALSE (0). */ -+#define qb_attr_code_for_ms(code, bits, expr) \ -+ for (; expr; qb_attr_code_rotate_ms(code, bits)) -+#define qb_attr_code_for_ls(code, bits, expr) \ -+ for (; expr; qb_attr_code_rotate_ls(code, bits)) -+ -+static inline void word_copy(void *d, const void *s, unsigned int cnt) -+{ -+ u32 *dd = d; -+ const u32 *ss = s; -+ -+ while (cnt--) -+ *(dd++) = *(ss++); -+} -+ -+/* -+ * Currently, the CENA support code expects each 32-bit word to be written in -+ * host order, and these are converted to hardware (little-endian) order on -+ * command submission. However, 64-bit quantities are must be written (and read) -+ * as two 32-bit words with the least-significant word first, irrespective of -+ * host endianness. -+ */ -+static inline void u64_to_le32_copy(void *d, const u64 *s, -+ unsigned int cnt) -+{ -+ u32 *dd = d; -+ const u32 *ss = (const u32 *)s; -+ -+ while (cnt--) { -+ /* -+ * TBD: the toolchain was choking on the use of 64-bit types up -+ * until recently so this works entirely with 32-bit variables. -+ * When 64-bit types become usable again, investigate better -+ * ways of doing this. -+ */ -+#if defined(__BIG_ENDIAN) -+ *(dd++) = ss[1]; -+ *(dd++) = ss[0]; -+ ss += 2; -+#else -+ *(dd++) = *(ss++); -+ *(dd++) = *(ss++); -+#endif -+ } -+} -+ -+static inline void u64_from_le32_copy(u64 *d, const void *s, -+ unsigned int cnt) -+{ -+ const u32 *ss = s; -+ u32 *dd = (u32 *)d; -+ -+ while (cnt--) { -+#if defined(__BIG_ENDIAN) -+ dd[1] = *(ss++); -+ dd[0] = *(ss++); -+ dd += 2; -+#else -+ *(dd++) = *(ss++); -+ *(dd++) = *(ss++); -+#endif -+ } -+} -+ -+/* decode a field from a cacheline */ -+static inline u32 qb_attr_code_decode(const struct qb_attr_code *code, -+ const u32 *cacheline) -+{ -+ return d32_u32(code->lsoffset, code->width, cacheline[code->word]); -+} -+ -+static inline u64 qb_attr_code_decode_64(const struct qb_attr_code *code, -+ const u64 *cacheline) -+{ -+ u64 res; -+ -+ u64_from_le32_copy(&res, &cacheline[code->word / 2], 1); -+ return res; -+} -+ -+/* encode a field to a cacheline */ -+static inline void qb_attr_code_encode(const struct qb_attr_code *code, -+ u32 *cacheline, u32 val) -+{ -+ cacheline[code->word] = -+ r32_u32(code->lsoffset, code->width, cacheline[code->word]) -+ | e32_u32(code->lsoffset, code->width, val); -+} -+ -+static inline void qb_attr_code_encode_64(const struct qb_attr_code *code, -+ u64 *cacheline, u64 val) -+{ -+ u64_to_le32_copy(&cacheline[code->word / 2], &val, 1); -+} -+ -+/* Small-width signed values (two's-complement) will decode into medium-width -+ * positives. (Eg. for an 8-bit signed field, which stores values from -128 to -+ * +127, a setting of -7 would appear to decode to the 32-bit unsigned value -+ * 249. Likewise -120 would decode as 136.) This function allows the caller to -+ * "re-sign" such fields to 32-bit signed. (Eg. -7, which was 249 with an 8-bit -+ * encoding, will become 0xfffffff9 if you cast the return value to u32). -+ */ -+static inline int32_t qb_attr_code_makesigned(const struct qb_attr_code *code, -+ u32 val) -+{ -+ WARN_ON(val >= (1 << code->width)); -+ /* If the high bit was set, it was encoding a negative */ -+ if (val >= (1 << (code->width - 1))) -+ return (int32_t)0 - (int32_t)(((u32)1 << code->width) - -+ val); -+ /* Otherwise, it was encoding a positive */ -+ return (int32_t)val; -+} -+ -+/* ---------------------- */ -+/* Descriptors/cachelines */ -+/* ---------------------- */ -+ -+/* To avoid needless dynamic allocation, the driver API often gives the caller -+ * a "descriptor" type that the caller can instantiate however they like. -+ * Ultimately though, it is just a cacheline of binary storage (or something -+ * smaller when it is known that the descriptor doesn't need all 64 bytes) for -+ * holding pre-formatted pieces of hardware commands. The performance-critical -+ * code can then copy these descriptors directly into hardware command -+ * registers more efficiently than trying to construct/format commands -+ * on-the-fly. The API user sees the descriptor as an array of 32-bit words in -+ * order for the compiler to know its size, but the internal details are not -+ * exposed. The following macro is used within the driver for converting *any* -+ * descriptor pointer to a usable array pointer. The use of a macro (instead of -+ * an inline) is necessary to work with different descriptor types and to work -+ * correctly with const and non-const inputs (and similarly-qualified outputs). -+ */ -+#define qb_cl(d) (&(d)->dont_manipulate_directly[0]) -+ -+#endif /* __FSL_QBMAN_PORTAL_H */ ---- /dev/null -+++ b/drivers/staging/fsl-mc/bus/dpio/qbman_debug.c -@@ -0,0 +1,853 @@ -+/* Copyright (C) 2015 Freescale Semiconductor, Inc. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are met: -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * * Neither the name of Freescale Semiconductor nor the -+ * names of its contributors may be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") as published by the Free Software -+ * Foundation, either version 2 of that License or (at your option) any -+ * later version. -+ * -+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY -+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY -+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include <linux/errno.h> -+ -+#include "../../include/dpaa2-global.h" -+#include "qbman-portal.h" -+#include "qbman_debug.h" -+ -+/* QBMan portal management command code */ -+#define QBMAN_BP_QUERY 0x32 -+#define QBMAN_FQ_QUERY 0x44 -+#define QBMAN_FQ_QUERY_NP 0x45 -+#define QBMAN_CGR_QUERY 0x51 -+#define QBMAN_WRED_QUERY 0x54 -+#define QBMAN_CGR_STAT_QUERY 0x55 -+#define QBMAN_CGR_STAT_QUERY_CLR 0x56 -+ -+enum qbman_attr_usage_e { -+ qbman_attr_usage_fq, -+ qbman_attr_usage_bpool, -+ qbman_attr_usage_cgr, -+}; -+ -+struct int_qbman_attr { -+ u32 words[32]; -+ enum qbman_attr_usage_e usage; ++/* Query APIs */ ++struct qbman_fq_query_np_rslt { ++ u8 verb; ++ u8 rslt; ++ u8 st1; ++ u8 st2; ++ u8 reserved[2]; ++ u16 od1_sfdr; ++ u16 od2_sfdr; ++ u16 od3_sfdr; ++ u16 ra1_sfdr; ++ u16 ra2_sfdr; ++ u32 pfdr_hptr; ++ u32 pfdr_tptr; ++ u32 frm_cnt; ++ u32 byte_cnt; ++ u16 ics_surp; ++ u8 is; ++ u8 reserved2[29]; +}; + -+#define attr_type_set(a, e) \ -+{ \ -+ struct qbman_attr *__attr = a; \ -+ enum qbman_attr_usage_e __usage = e; \ -+ ((struct int_qbman_attr *)__attr)->usage = __usage; \ -+} -+ -+#define ATTR32(d) (&(d)->dont_manipulate_directly[0]) -+#define ATTR32_1(d) (&(d)->dont_manipulate_directly[16]) -+ -+static struct qb_attr_code code_bp_bpid = QB_CODE(0, 16, 16); -+static struct qb_attr_code code_bp_bdi = QB_CODE(1, 16, 1); -+static struct qb_attr_code code_bp_va = QB_CODE(1, 17, 1); -+static struct qb_attr_code code_bp_wae = QB_CODE(1, 18, 1); -+static struct qb_attr_code code_bp_swdet = QB_CODE(4, 0, 16); -+static struct qb_attr_code code_bp_swdxt = QB_CODE(4, 16, 16); -+static struct qb_attr_code code_bp_hwdet = QB_CODE(5, 0, 16); -+static struct qb_attr_code code_bp_hwdxt = QB_CODE(5, 16, 16); -+static struct qb_attr_code code_bp_swset = QB_CODE(6, 0, 16); -+static struct qb_attr_code code_bp_swsxt = QB_CODE(6, 16, 16); -+static struct qb_attr_code code_bp_vbpid = QB_CODE(7, 0, 14); -+static struct qb_attr_code code_bp_icid = QB_CODE(7, 16, 15); -+static struct qb_attr_code code_bp_pl = QB_CODE(7, 31, 1); -+static struct qb_attr_code code_bp_bpscn_addr_lo = QB_CODE(8, 0, 32); -+static struct qb_attr_code code_bp_bpscn_addr_hi = QB_CODE(9, 0, 32); -+static struct qb_attr_code code_bp_bpscn_ctx_lo = QB_CODE(10, 0, 32); -+static struct qb_attr_code code_bp_bpscn_ctx_hi = QB_CODE(11, 0, 32); -+static struct qb_attr_code code_bp_hw_targ = QB_CODE(12, 0, 16); -+static struct qb_attr_code code_bp_state = QB_CODE(1, 24, 3); -+static struct qb_attr_code code_bp_fill = QB_CODE(2, 0, 32); -+static struct qb_attr_code code_bp_hdptr = QB_CODE(3, 0, 32); -+static struct qb_attr_code code_bp_sdcnt = QB_CODE(13, 0, 8); -+static struct qb_attr_code code_bp_hdcnt = QB_CODE(13, 1, 8); -+static struct qb_attr_code code_bp_sscnt = QB_CODE(13, 2, 8); -+ -+void qbman_bp_attr_clear(struct qbman_attr *a) -+{ -+ memset(a, 0, sizeof(*a)); -+ attr_type_set(a, qbman_attr_usage_bpool); -+} -+ -+int qbman_bp_query(struct qbman_swp *s, u32 bpid, -+ struct qbman_attr *a) -+{ -+ u32 *p; -+ u32 verb, rslt; -+ u32 *attr = ATTR32(a); -+ -+ qbman_bp_attr_clear(a); -+ -+ /* Start the management command */ -+ p = qbman_swp_mc_start(s); -+ if (!p) -+ return -EBUSY; -+ -+ /* Encode the caller-provided attributes */ -+ qb_attr_code_encode(&code_bp_bpid, p, bpid); -+ -+ /* Complete the management command */ -+ p = qbman_swp_mc_complete(s, p, QBMAN_BP_QUERY); -+ -+ /* Decode the outcome */ -+ verb = qb_attr_code_decode(&code_generic_verb, p); -+ rslt = qb_attr_code_decode(&code_generic_rslt, p); -+ WARN_ON(verb != QBMAN_BP_QUERY); -+ -+ /* Determine success or failure */ -+ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) { -+ pr_err("Query of BPID 0x%x failed, code=0x%02x\n", bpid, rslt); -+ return -EIO; -+ } -+ -+ /* For the query, word[0] of the result contains only the -+ * verb/rslt fields, so skip word[0]. -+ */ -+ word_copy(&attr[1], &p[1], 15); -+ return 0; -+} -+ -+void qbman_bp_attr_get_bdi(struct qbman_attr *a, int *bdi, int *va, int *wae) -+{ -+ u32 *p = ATTR32(a); -+ -+ *bdi = !!qb_attr_code_decode(&code_bp_bdi, p); -+ *va = !!qb_attr_code_decode(&code_bp_va, p); -+ *wae = !!qb_attr_code_decode(&code_bp_wae, p); -+} -+ -+static u32 qbman_bp_thresh_to_value(u32 val) -+{ -+ return (val & 0xff) << ((val & 0xf00) >> 8); -+} -+ -+void qbman_bp_attr_get_swdet(struct qbman_attr *a, u32 *swdet) -+{ -+ u32 *p = ATTR32(a); -+ -+ *swdet = qbman_bp_thresh_to_value(qb_attr_code_decode(&code_bp_swdet, -+ p)); -+} -+ -+void qbman_bp_attr_get_swdxt(struct qbman_attr *a, u32 *swdxt) -+{ -+ u32 *p = ATTR32(a); -+ -+ *swdxt = qbman_bp_thresh_to_value(qb_attr_code_decode(&code_bp_swdxt, -+ p)); -+} -+ -+void qbman_bp_attr_get_hwdet(struct qbman_attr *a, u32 *hwdet) -+{ -+ u32 *p = ATTR32(a); -+ -+ *hwdet = qbman_bp_thresh_to_value(qb_attr_code_decode(&code_bp_hwdet, -+ p)); -+} -+ -+void qbman_bp_attr_get_hwdxt(struct qbman_attr *a, u32 *hwdxt) -+{ -+ u32 *p = ATTR32(a); -+ -+ *hwdxt = qbman_bp_thresh_to_value(qb_attr_code_decode(&code_bp_hwdxt, -+ p)); -+} -+ -+void qbman_bp_attr_get_swset(struct qbman_attr *a, u32 *swset) -+{ -+ u32 *p = ATTR32(a); -+ -+ *swset = qbman_bp_thresh_to_value(qb_attr_code_decode(&code_bp_swset, -+ p)); -+} -+ -+void qbman_bp_attr_get_swsxt(struct qbman_attr *a, u32 *swsxt) -+{ -+ u32 *p = ATTR32(a); -+ -+ *swsxt = qbman_bp_thresh_to_value(qb_attr_code_decode(&code_bp_swsxt, -+ p)); -+} -+ -+void qbman_bp_attr_get_vbpid(struct qbman_attr *a, u32 *vbpid) -+{ -+ u32 *p = ATTR32(a); -+ -+ *vbpid = qb_attr_code_decode(&code_bp_vbpid, p); -+} -+ -+void qbman_bp_attr_get_icid(struct qbman_attr *a, u32 *icid, int *pl) -+{ -+ u32 *p = ATTR32(a); -+ -+ *icid = qb_attr_code_decode(&code_bp_icid, p); -+ *pl = !!qb_attr_code_decode(&code_bp_pl, p); -+} -+ -+void qbman_bp_attr_get_bpscn_addr(struct qbman_attr *a, u64 *bpscn_addr) -+{ -+ u32 *p = ATTR32(a); -+ -+ *bpscn_addr = ((u64)qb_attr_code_decode(&code_bp_bpscn_addr_hi, -+ p) << 32) | -+ (u64)qb_attr_code_decode(&code_bp_bpscn_addr_lo, -+ p); -+} -+ -+void qbman_bp_attr_get_bpscn_ctx(struct qbman_attr *a, u64 *bpscn_ctx) -+{ -+ u32 *p = ATTR32(a); -+ -+ *bpscn_ctx = ((u64)qb_attr_code_decode(&code_bp_bpscn_ctx_hi, p) -+ << 32) | -+ (u64)qb_attr_code_decode(&code_bp_bpscn_ctx_lo, -+ p); -+} -+ -+void qbman_bp_attr_get_hw_targ(struct qbman_attr *a, u32 *hw_targ) -+{ -+ u32 *p = ATTR32(a); -+ -+ *hw_targ = qb_attr_code_decode(&code_bp_hw_targ, p); -+} -+ -+int qbman_bp_info_has_free_bufs(struct qbman_attr *a) -+{ -+ u32 *p = ATTR32(a); -+ -+ return !(int)(qb_attr_code_decode(&code_bp_state, p) & 0x1); -+} -+ -+int qbman_bp_info_is_depleted(struct qbman_attr *a) -+{ -+ u32 *p = ATTR32(a); -+ -+ return (int)(qb_attr_code_decode(&code_bp_state, p) & 0x2); -+} -+ -+int qbman_bp_info_is_surplus(struct qbman_attr *a) -+{ -+ u32 *p = ATTR32(a); -+ -+ return (int)(qb_attr_code_decode(&code_bp_state, p) & 0x4); -+} -+ -+u32 qbman_bp_info_num_free_bufs(struct qbman_attr *a) -+{ -+ u32 *p = ATTR32(a); -+ -+ return qb_attr_code_decode(&code_bp_fill, p); -+} -+ -+u32 qbman_bp_info_hdptr(struct qbman_attr *a) -+{ -+ u32 *p = ATTR32(a); -+ -+ return qb_attr_code_decode(&code_bp_hdptr, p); -+} -+ -+u32 qbman_bp_info_sdcnt(struct qbman_attr *a) -+{ -+ u32 *p = ATTR32(a); -+ -+ return qb_attr_code_decode(&code_bp_sdcnt, p); -+} -+ -+u32 qbman_bp_info_hdcnt(struct qbman_attr *a) -+{ -+ u32 *p = ATTR32(a); -+ -+ return qb_attr_code_decode(&code_bp_hdcnt, p); -+} -+ -+u32 qbman_bp_info_sscnt(struct qbman_attr *a) -+{ -+ u32 *p = ATTR32(a); -+ -+ return qb_attr_code_decode(&code_bp_sscnt, p); -+} -+ -+static struct qb_attr_code code_fq_fqid = QB_CODE(1, 0, 24); -+static struct qb_attr_code code_fq_cgrid = QB_CODE(2, 16, 16); -+static struct qb_attr_code code_fq_destwq = QB_CODE(3, 0, 15); -+static struct qb_attr_code code_fq_fqctrl = QB_CODE(3, 24, 8); -+static struct qb_attr_code code_fq_icscred = QB_CODE(4, 0, 15); -+static struct qb_attr_code code_fq_tdthresh = QB_CODE(4, 16, 13); -+static struct qb_attr_code code_fq_oa_len = QB_CODE(5, 0, 12); -+static struct qb_attr_code code_fq_oa_ics = QB_CODE(5, 14, 1); -+static struct qb_attr_code code_fq_oa_cgr = QB_CODE(5, 15, 1); -+static struct qb_attr_code code_fq_mctl_bdi = QB_CODE(5, 24, 1); -+static struct qb_attr_code code_fq_mctl_ff = QB_CODE(5, 25, 1); -+static struct qb_attr_code code_fq_mctl_va = QB_CODE(5, 26, 1); -+static struct qb_attr_code code_fq_mctl_ps = QB_CODE(5, 27, 1); -+static struct qb_attr_code code_fq_ctx_lower32 = QB_CODE(6, 0, 32); -+static struct qb_attr_code code_fq_ctx_upper32 = QB_CODE(7, 0, 32); -+static struct qb_attr_code code_fq_icid = QB_CODE(8, 0, 15); -+static struct qb_attr_code code_fq_pl = QB_CODE(8, 15, 1); -+static struct qb_attr_code code_fq_vfqid = QB_CODE(9, 0, 24); -+static struct qb_attr_code code_fq_erfqid = QB_CODE(10, 0, 24); -+ -+void qbman_fq_attr_clear(struct qbman_attr *a) -+{ -+ memset(a, 0, sizeof(*a)); -+ attr_type_set(a, qbman_attr_usage_fq); -+} -+ -+/* FQ query function for programmable fields */ -+int qbman_fq_query(struct qbman_swp *s, u32 fqid, struct qbman_attr *desc) -+{ -+ u32 *p; -+ u32 verb, rslt; -+ u32 *d = ATTR32(desc); -+ -+ qbman_fq_attr_clear(desc); -+ -+ p = qbman_swp_mc_start(s); -+ if (!p) -+ return -EBUSY; -+ qb_attr_code_encode(&code_fq_fqid, p, fqid); -+ p = qbman_swp_mc_complete(s, p, QBMAN_FQ_QUERY); -+ -+ /* Decode the outcome */ -+ verb = qb_attr_code_decode(&code_generic_verb, p); -+ rslt = qb_attr_code_decode(&code_generic_rslt, p); -+ WARN_ON(verb != QBMAN_FQ_QUERY); -+ -+ /* Determine success or failure */ -+ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) { -+ pr_err("Query of FQID 0x%x failed, code=0x%02x\n", -+ fqid, rslt); -+ return -EIO; -+ } -+ /* -+ * For the configure, word[0] of the command contains only the WE-mask. -+ * For the query, word[0] of the result contains only the verb/rslt -+ * fields. Skip word[0] in the latter case. -+ */ -+ word_copy(&d[1], &p[1], 15); -+ return 0; -+} -+ -+void qbman_fq_attr_get_fqctrl(struct qbman_attr *d, u32 *fqctrl) -+{ -+ u32 *p = ATTR32(d); -+ -+ *fqctrl = qb_attr_code_decode(&code_fq_fqctrl, p); -+} -+ -+void qbman_fq_attr_get_cgrid(struct qbman_attr *d, u32 *cgrid) -+{ -+ u32 *p = ATTR32(d); -+ -+ *cgrid = qb_attr_code_decode(&code_fq_cgrid, p); -+} -+ -+void qbman_fq_attr_get_destwq(struct qbman_attr *d, u32 *destwq) -+{ -+ u32 *p = ATTR32(d); -+ -+ *destwq = qb_attr_code_decode(&code_fq_destwq, p); -+} -+ -+void qbman_fq_attr_get_icscred(struct qbman_attr *d, u32 *icscred) -+{ -+ u32 *p = ATTR32(d); -+ -+ *icscred = qb_attr_code_decode(&code_fq_icscred, p); -+} -+ -+static struct qb_attr_code code_tdthresh_exp = QB_CODE(0, 0, 5); -+static struct qb_attr_code code_tdthresh_mant = QB_CODE(0, 5, 8); -+static u32 qbman_thresh_to_value(u32 val) -+{ -+ u32 m, e; -+ -+ m = qb_attr_code_decode(&code_tdthresh_mant, &val); -+ e = qb_attr_code_decode(&code_tdthresh_exp, &val); -+ return m << e; -+} -+ -+void qbman_fq_attr_get_tdthresh(struct qbman_attr *d, u32 *tdthresh) -+{ -+ u32 *p = ATTR32(d); -+ -+ *tdthresh = qbman_thresh_to_value(qb_attr_code_decode(&code_fq_tdthresh, -+ p)); -+} -+ -+void qbman_fq_attr_get_oa(struct qbman_attr *d, -+ int *oa_ics, int *oa_cgr, int32_t *oa_len) -+{ -+ u32 *p = ATTR32(d); -+ -+ *oa_ics = !!qb_attr_code_decode(&code_fq_oa_ics, p); -+ *oa_cgr = !!qb_attr_code_decode(&code_fq_oa_cgr, p); -+ *oa_len = qb_attr_code_makesigned(&code_fq_oa_len, -+ qb_attr_code_decode(&code_fq_oa_len, p)); -+} -+ -+void qbman_fq_attr_get_mctl(struct qbman_attr *d, -+ int *bdi, int *ff, int *va, int *ps) -+{ -+ u32 *p = ATTR32(d); -+ -+ *bdi = !!qb_attr_code_decode(&code_fq_mctl_bdi, p); -+ *ff = !!qb_attr_code_decode(&code_fq_mctl_ff, p); -+ *va = !!qb_attr_code_decode(&code_fq_mctl_va, p); -+ *ps = !!qb_attr_code_decode(&code_fq_mctl_ps, p); -+} -+ -+void qbman_fq_attr_get_ctx(struct qbman_attr *d, u32 *hi, u32 *lo) -+{ -+ u32 *p = ATTR32(d); -+ -+ *hi = qb_attr_code_decode(&code_fq_ctx_upper32, p); -+ *lo = qb_attr_code_decode(&code_fq_ctx_lower32, p); -+} -+ -+void qbman_fq_attr_get_icid(struct qbman_attr *d, u32 *icid, int *pl) -+{ -+ u32 *p = ATTR32(d); -+ -+ *icid = qb_attr_code_decode(&code_fq_icid, p); -+ *pl = !!qb_attr_code_decode(&code_fq_pl, p); -+} -+ -+void qbman_fq_attr_get_vfqid(struct qbman_attr *d, u32 *vfqid) -+{ -+ u32 *p = ATTR32(d); -+ -+ *vfqid = qb_attr_code_decode(&code_fq_vfqid, p); -+} -+ -+void qbman_fq_attr_get_erfqid(struct qbman_attr *d, u32 *erfqid) -+{ -+ u32 *p = ATTR32(d); -+ -+ *erfqid = qb_attr_code_decode(&code_fq_erfqid, p); -+} -+ -+/* Query FQ Non-Programmalbe Fields */ -+static struct qb_attr_code code_fq_np_state = QB_CODE(0, 16, 3); -+static struct qb_attr_code code_fq_np_fe = QB_CODE(0, 19, 1); -+static struct qb_attr_code code_fq_np_x = QB_CODE(0, 20, 1); -+static struct qb_attr_code code_fq_np_r = QB_CODE(0, 21, 1); -+static struct qb_attr_code code_fq_np_oe = QB_CODE(0, 22, 1); -+static struct qb_attr_code code_fq_np_frm_cnt = QB_CODE(6, 0, 24); -+static struct qb_attr_code code_fq_np_byte_cnt = QB_CODE(7, 0, 32); -+ +int qbman_fq_query_state(struct qbman_swp *s, u32 fqid, -+ struct qbman_attr *state) -+{ -+ u32 *p; -+ u32 verb, rslt; -+ u32 *d = ATTR32(state); -+ -+ qbman_fq_attr_clear(state); -+ -+ p = qbman_swp_mc_start(s); -+ if (!p) -+ return -EBUSY; -+ qb_attr_code_encode(&code_fq_fqid, p, fqid); -+ p = qbman_swp_mc_complete(s, p, QBMAN_FQ_QUERY_NP); -+ -+ /* Decode the outcome */ -+ verb = qb_attr_code_decode(&code_generic_verb, p); -+ rslt = qb_attr_code_decode(&code_generic_rslt, p); -+ WARN_ON(verb != QBMAN_FQ_QUERY_NP); -+ -+ /* Determine success or failure */ -+ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) { -+ pr_err("Query NP fields of FQID 0x%x failed, code=0x%02x\n", -+ fqid, rslt); -+ return -EIO; -+ } -+ word_copy(&d[0], &p[0], 16); -+ return 0; -+} -+ -+u32 qbman_fq_state_schedstate(const struct qbman_attr *state) -+{ -+ const u32 *p = ATTR32(state); -+ -+ return qb_attr_code_decode(&code_fq_np_state, p); -+} -+ -+int qbman_fq_state_force_eligible(const struct qbman_attr *state) -+{ -+ const u32 *p = ATTR32(state); -+ -+ return !!qb_attr_code_decode(&code_fq_np_fe, p); -+} -+ -+int qbman_fq_state_xoff(const struct qbman_attr *state) -+{ -+ const u32 *p = ATTR32(state); -+ -+ return !!qb_attr_code_decode(&code_fq_np_x, p); -+} -+ -+int qbman_fq_state_retirement_pending(const struct qbman_attr *state) -+{ -+ const u32 *p = ATTR32(state); -+ -+ return !!qb_attr_code_decode(&code_fq_np_r, p); -+} -+ -+int qbman_fq_state_overflow_error(const struct qbman_attr *state) -+{ -+ const u32 *p = ATTR32(state); -+ -+ return !!qb_attr_code_decode(&code_fq_np_oe, p); -+} -+ -+u32 qbman_fq_state_frame_count(const struct qbman_attr *state) -+{ -+ const u32 *p = ATTR32(state); -+ -+ return qb_attr_code_decode(&code_fq_np_frm_cnt, p); -+} -+ -+u32 qbman_fq_state_byte_count(const struct qbman_attr *state) -+{ -+ const u32 *p = ATTR32(state); -+ -+ return qb_attr_code_decode(&code_fq_np_byte_cnt, p); -+} -+ -+/* Query CGR */ -+static struct qb_attr_code code_cgr_cgid = QB_CODE(0, 16, 16); -+static struct qb_attr_code code_cgr_cscn_wq_en_enter = QB_CODE(2, 0, 1); -+static struct qb_attr_code code_cgr_cscn_wq_en_exit = QB_CODE(2, 1, 1); -+static struct qb_attr_code code_cgr_cscn_wq_icd = QB_CODE(2, 2, 1); -+static struct qb_attr_code code_cgr_mode = QB_CODE(3, 16, 2); -+static struct qb_attr_code code_cgr_rej_cnt_mode = QB_CODE(3, 18, 1); -+static struct qb_attr_code code_cgr_cscn_bdi = QB_CODE(3, 19, 1); -+static struct qb_attr_code code_cgr_cscn_wr_en_enter = QB_CODE(3, 24, 1); -+static struct qb_attr_code code_cgr_cscn_wr_en_exit = QB_CODE(3, 25, 1); -+static struct qb_attr_code code_cgr_cg_wr_ae = QB_CODE(3, 26, 1); -+static struct qb_attr_code code_cgr_cscn_dcp_en = QB_CODE(3, 27, 1); -+static struct qb_attr_code code_cgr_cg_wr_va = QB_CODE(3, 28, 1); -+static struct qb_attr_code code_cgr_i_cnt_wr_en = QB_CODE(4, 0, 1); -+static struct qb_attr_code code_cgr_i_cnt_wr_bnd = QB_CODE(4, 1, 5); -+static struct qb_attr_code code_cgr_td_en = QB_CODE(4, 8, 1); -+static struct qb_attr_code code_cgr_cs_thres = QB_CODE(4, 16, 13); -+static struct qb_attr_code code_cgr_cs_thres_x = QB_CODE(5, 0, 13); -+static struct qb_attr_code code_cgr_td_thres = QB_CODE(5, 16, 13); -+static struct qb_attr_code code_cgr_cscn_tdcp = QB_CODE(6, 0, 16); -+static struct qb_attr_code code_cgr_cscn_wqid = QB_CODE(6, 16, 16); -+static struct qb_attr_code code_cgr_cscn_vcgid = QB_CODE(7, 0, 16); -+static struct qb_attr_code code_cgr_cg_icid = QB_CODE(7, 16, 15); -+static struct qb_attr_code code_cgr_cg_pl = QB_CODE(7, 31, 1); -+static struct qb_attr_code code_cgr_cg_wr_addr_lo = QB_CODE(8, 0, 32); -+static struct qb_attr_code code_cgr_cg_wr_addr_hi = QB_CODE(9, 0, 32); -+static struct qb_attr_code code_cgr_cscn_ctx_lo = QB_CODE(10, 0, 32); -+static struct qb_attr_code code_cgr_cscn_ctx_hi = QB_CODE(11, 0, 32); ++ struct qbman_fq_query_np_rslt *r); ++u32 qbman_fq_state_frame_count(const struct qbman_fq_query_np_rslt *r); ++u32 qbman_fq_state_byte_count(const struct qbman_fq_query_np_rslt *r); + -+void qbman_cgr_attr_clear(struct qbman_attr *a) -+{ -+ memset(a, 0, sizeof(*a)); -+ attr_type_set(a, qbman_attr_usage_cgr); -+} -+ -+int qbman_cgr_query(struct qbman_swp *s, u32 cgid, struct qbman_attr *attr) -+{ -+ u32 *p; -+ u32 verb, rslt; -+ u32 *d[2]; -+ int i; -+ u32 query_verb; -+ -+ d[0] = ATTR32(attr); -+ d[1] = ATTR32_1(attr); -+ -+ qbman_cgr_attr_clear(attr); -+ -+ for (i = 0; i < 2; i++) { -+ p = qbman_swp_mc_start(s); -+ if (!p) -+ return -EBUSY; -+ query_verb = i ? QBMAN_WRED_QUERY : QBMAN_CGR_QUERY; -+ -+ qb_attr_code_encode(&code_cgr_cgid, p, cgid); -+ p = qbman_swp_mc_complete(s, p, p[0] | query_verb); -+ -+ /* Decode the outcome */ -+ verb = qb_attr_code_decode(&code_generic_verb, p); -+ rslt = qb_attr_code_decode(&code_generic_rslt, p); -+ WARN_ON(verb != query_verb); -+ -+ /* Determine success or failure */ -+ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) { -+ pr_err("Query CGID 0x%x failed,", cgid); -+ pr_err(" verb=0x%02x, code=0x%02x\n", verb, rslt); -+ return -EIO; -+ } -+ /* For the configure, word[0] of the command contains only the -+ * verb/cgid. For the query, word[0] of the result contains -+ * only the verb/rslt fields. Skip word[0] in the latter case. -+ */ -+ word_copy(&d[i][1], &p[1], 15); -+ } -+ return 0; -+} -+ -+void qbman_cgr_attr_get_ctl1(struct qbman_attr *d, int *cscn_wq_en_enter, -+ int *cscn_wq_en_exit, int *cscn_wq_icd) -+ { -+ u32 *p = ATTR32(d); -+ *cscn_wq_en_enter = !!qb_attr_code_decode(&code_cgr_cscn_wq_en_enter, -+ p); -+ *cscn_wq_en_exit = !!qb_attr_code_decode(&code_cgr_cscn_wq_en_exit, p); -+ *cscn_wq_icd = !!qb_attr_code_decode(&code_cgr_cscn_wq_icd, p); -+} -+ -+void qbman_cgr_attr_get_mode(struct qbman_attr *d, u32 *mode, -+ int *rej_cnt_mode, int *cscn_bdi) -+{ -+ u32 *p = ATTR32(d); -+ *mode = qb_attr_code_decode(&code_cgr_mode, p); -+ *rej_cnt_mode = !!qb_attr_code_decode(&code_cgr_rej_cnt_mode, p); -+ *cscn_bdi = !!qb_attr_code_decode(&code_cgr_cscn_bdi, p); -+} -+ -+void qbman_cgr_attr_get_ctl2(struct qbman_attr *d, int *cscn_wr_en_enter, -+ int *cscn_wr_en_exit, int *cg_wr_ae, -+ int *cscn_dcp_en, int *cg_wr_va) -+{ -+ u32 *p = ATTR32(d); -+ *cscn_wr_en_enter = !!qb_attr_code_decode(&code_cgr_cscn_wr_en_enter, -+ p); -+ *cscn_wr_en_exit = !!qb_attr_code_decode(&code_cgr_cscn_wr_en_exit, p); -+ *cg_wr_ae = !!qb_attr_code_decode(&code_cgr_cg_wr_ae, p); -+ *cscn_dcp_en = !!qb_attr_code_decode(&code_cgr_cscn_dcp_en, p); -+ *cg_wr_va = !!qb_attr_code_decode(&code_cgr_cg_wr_va, p); -+} -+ -+void qbman_cgr_attr_get_iwc(struct qbman_attr *d, int *i_cnt_wr_en, -+ u32 *i_cnt_wr_bnd) -+{ -+ u32 *p = ATTR32(d); -+ *i_cnt_wr_en = !!qb_attr_code_decode(&code_cgr_i_cnt_wr_en, p); -+ *i_cnt_wr_bnd = qb_attr_code_decode(&code_cgr_i_cnt_wr_bnd, p); -+} -+ -+void qbman_cgr_attr_get_tdc(struct qbman_attr *d, int *td_en) -+{ -+ u32 *p = ATTR32(d); -+ *td_en = !!qb_attr_code_decode(&code_cgr_td_en, p); -+} -+ -+void qbman_cgr_attr_get_cs_thres(struct qbman_attr *d, u32 *cs_thres) -+{ -+ u32 *p = ATTR32(d); -+ *cs_thres = qbman_thresh_to_value(qb_attr_code_decode( -+ &code_cgr_cs_thres, p)); -+} -+ -+void qbman_cgr_attr_get_cs_thres_x(struct qbman_attr *d, -+ u32 *cs_thres_x) -+{ -+ u32 *p = ATTR32(d); -+ *cs_thres_x = qbman_thresh_to_value(qb_attr_code_decode( -+ &code_cgr_cs_thres_x, p)); -+} -+ -+void qbman_cgr_attr_get_td_thres(struct qbman_attr *d, u32 *td_thres) -+{ -+ u32 *p = ATTR32(d); -+ *td_thres = qbman_thresh_to_value(qb_attr_code_decode( -+ &code_cgr_td_thres, p)); -+} -+ -+void qbman_cgr_attr_get_cscn_tdcp(struct qbman_attr *d, u32 *cscn_tdcp) -+{ -+ u32 *p = ATTR32(d); -+ *cscn_tdcp = qb_attr_code_decode(&code_cgr_cscn_tdcp, p); -+} -+ -+void qbman_cgr_attr_get_cscn_wqid(struct qbman_attr *d, u32 *cscn_wqid) -+{ -+ u32 *p = ATTR32(d); -+ *cscn_wqid = qb_attr_code_decode(&code_cgr_cscn_wqid, p); -+} -+ -+void qbman_cgr_attr_get_cscn_vcgid(struct qbman_attr *d, -+ u32 *cscn_vcgid) -+{ -+ u32 *p = ATTR32(d); -+ *cscn_vcgid = qb_attr_code_decode(&code_cgr_cscn_vcgid, p); -+} -+ -+void qbman_cgr_attr_get_cg_icid(struct qbman_attr *d, u32 *icid, -+ int *pl) -+{ -+ u32 *p = ATTR32(d); -+ *icid = qb_attr_code_decode(&code_cgr_cg_icid, p); -+ *pl = !!qb_attr_code_decode(&code_cgr_cg_pl, p); -+} -+ -+void qbman_cgr_attr_get_cg_wr_addr(struct qbman_attr *d, -+ u64 *cg_wr_addr) -+{ -+ u32 *p = ATTR32(d); -+ *cg_wr_addr = ((u64)qb_attr_code_decode(&code_cgr_cg_wr_addr_hi, -+ p) << 32) | -+ (u64)qb_attr_code_decode(&code_cgr_cg_wr_addr_lo, -+ p); -+} -+ -+void qbman_cgr_attr_get_cscn_ctx(struct qbman_attr *d, u64 *cscn_ctx) -+{ -+ u32 *p = ATTR32(d); -+ *cscn_ctx = ((u64)qb_attr_code_decode(&code_cgr_cscn_ctx_hi, p) -+ << 32) | -+ (u64)qb_attr_code_decode(&code_cgr_cscn_ctx_lo, p); -+} -+ -+#define WRED_EDP_WORD(n) (18 + (n) / 4) -+#define WRED_EDP_OFFSET(n) (8 * ((n) % 4)) -+#define WRED_PARM_DP_WORD(n) ((n) + 20) -+#define WRED_WE_EDP(n) (16 + (n) * 2) -+#define WRED_WE_PARM_DP(n) (17 + (n) * 2) -+void qbman_cgr_attr_wred_get_edp(struct qbman_attr *d, u32 idx, -+ int *edp) -+{ -+ u32 *p = ATTR32(d); -+ struct qb_attr_code code_wred_edp = QB_CODE(WRED_EDP_WORD(idx), -+ WRED_EDP_OFFSET(idx), 8); -+ *edp = (int)qb_attr_code_decode(&code_wred_edp, p); -+} -+ -+void qbman_cgr_attr_wred_dp_decompose(u32 dp, u64 *minth, -+ u64 *maxth, u8 *maxp) -+{ -+ u8 ma, mn, step_i, step_s, pn; -+ -+ ma = (u8)(dp >> 24); -+ mn = (u8)(dp >> 19) & 0x1f; -+ step_i = (u8)(dp >> 11); -+ step_s = (u8)(dp >> 6) & 0x1f; -+ pn = (u8)dp & 0x3f; -+ -+ *maxp = ((pn << 2) * 100) / 256; -+ -+ if (mn == 0) -+ *maxth = ma; -+ else -+ *maxth = ((ma + 256) * (1 << (mn - 1))); -+ -+ if (step_s == 0) -+ *minth = *maxth - step_i; -+ else -+ *minth = *maxth - (256 + step_i) * (1 << (step_s - 1)); -+} -+ -+void qbman_cgr_attr_wred_get_parm_dp(struct qbman_attr *d, u32 idx, -+ u32 *dp) -+{ -+ u32 *p = ATTR32(d); -+ struct qb_attr_code code_wred_parm_dp = QB_CODE(WRED_PARM_DP_WORD(idx), -+ 0, 8); -+ *dp = qb_attr_code_decode(&code_wred_parm_dp, p); -+} -+ -+/* Query CGR/CCGR/CQ statistics */ -+static struct qb_attr_code code_cgr_stat_ct = QB_CODE(4, 0, 32); -+static struct qb_attr_code code_cgr_stat_frame_cnt_lo = QB_CODE(4, 0, 32); -+static struct qb_attr_code code_cgr_stat_frame_cnt_hi = QB_CODE(5, 0, 8); -+static struct qb_attr_code code_cgr_stat_byte_cnt_lo = QB_CODE(6, 0, 32); -+static struct qb_attr_code code_cgr_stat_byte_cnt_hi = QB_CODE(7, 0, 16); -+static int qbman_cgr_statistics_query(struct qbman_swp *s, u32 cgid, -+ int clear, u32 command_type, -+ u64 *frame_cnt, u64 *byte_cnt) -+{ -+ u32 *p; -+ u32 verb, rslt; -+ u32 query_verb; -+ u32 hi, lo; -+ -+ p = qbman_swp_mc_start(s); -+ if (!p) -+ return -EBUSY; -+ -+ qb_attr_code_encode(&code_cgr_cgid, p, cgid); -+ if (command_type < 2) -+ qb_attr_code_encode(&code_cgr_stat_ct, p, command_type); -+ query_verb = clear ? -+ QBMAN_CGR_STAT_QUERY_CLR : QBMAN_CGR_STAT_QUERY; -+ p = qbman_swp_mc_complete(s, p, p[0] | query_verb); -+ -+ /* Decode the outcome */ -+ verb = qb_attr_code_decode(&code_generic_verb, p); -+ rslt = qb_attr_code_decode(&code_generic_rslt, p); -+ WARN_ON(verb != query_verb); -+ -+ /* Determine success or failure */ -+ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) { -+ pr_err("Query statistics of CGID 0x%x failed,", cgid); -+ pr_err(" verb=0x%02x code=0x%02x\n", verb, rslt); -+ return -EIO; -+ } -+ -+ if (*frame_cnt) { -+ hi = qb_attr_code_decode(&code_cgr_stat_frame_cnt_hi, p); -+ lo = qb_attr_code_decode(&code_cgr_stat_frame_cnt_lo, p); -+ *frame_cnt = ((u64)hi << 32) | (u64)lo; -+ } -+ if (*byte_cnt) { -+ hi = qb_attr_code_decode(&code_cgr_stat_byte_cnt_hi, p); -+ lo = qb_attr_code_decode(&code_cgr_stat_byte_cnt_lo, p); -+ *byte_cnt = ((u64)hi << 32) | (u64)lo; -+ } -+ -+ return 0; -+} -+ -+int qbman_cgr_reject_statistics(struct qbman_swp *s, u32 cgid, int clear, -+ u64 *frame_cnt, u64 *byte_cnt) -+{ -+ return qbman_cgr_statistics_query(s, cgid, clear, 0xff, -+ frame_cnt, byte_cnt); -+} -+ -+int qbman_ccgr_reject_statistics(struct qbman_swp *s, u32 cgid, int clear, -+ u64 *frame_cnt, u64 *byte_cnt) -+{ -+ return qbman_cgr_statistics_query(s, cgid, clear, 1, -+ frame_cnt, byte_cnt); -+} -+ -+int qbman_cq_dequeue_statistics(struct qbman_swp *s, u32 cgid, int clear, -+ u64 *frame_cnt, u64 *byte_cnt) -+{ -+ return qbman_cgr_statistics_query(s, cgid, clear, 0, -+ frame_cnt, byte_cnt); -+} ---- /dev/null -+++ b/drivers/staging/fsl-mc/bus/dpio/qbman_debug.h -@@ -0,0 +1,136 @@ -+/* Copyright (C) 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. -+ */ -+ -+struct qbman_attr { -+ u32 dont_manipulate_directly[40]; ++struct qbman_bp_query_rslt { ++ u8 verb; ++ u8 rslt; ++ u8 reserved[4]; ++ u8 bdi; ++ u8 state; ++ u32 fill; ++ u32 hdotr; ++ u16 swdet; ++ u16 swdxt; ++ u16 hwdet; ++ u16 hwdxt; ++ u16 swset; ++ u16 swsxt; ++ u16 vbpid; ++ u16 icid; ++ u64 bpscn_addr; ++ u64 bpscn_ctx; ++ u16 hw_targ; ++ u8 dbe; ++ u8 reserved2; ++ u8 sdcnt; ++ u8 hdcnt; ++ u8 sscnt; ++ u8 reserved3[9]; +}; + -+/* Buffer pool query commands */ +int qbman_bp_query(struct qbman_swp *s, u32 bpid, -+ struct qbman_attr *a); -+void qbman_bp_attr_get_bdi(struct qbman_attr *a, int *bdi, int *va, int *wae); -+void qbman_bp_attr_get_swdet(struct qbman_attr *a, u32 *swdet); -+void qbman_bp_attr_get_swdxt(struct qbman_attr *a, u32 *swdxt); -+void qbman_bp_attr_get_hwdet(struct qbman_attr *a, u32 *hwdet); -+void qbman_bp_attr_get_hwdxt(struct qbman_attr *a, u32 *hwdxt); -+void qbman_bp_attr_get_swset(struct qbman_attr *a, u32 *swset); -+void qbman_bp_attr_get_swsxt(struct qbman_attr *a, u32 *swsxt); -+void qbman_bp_attr_get_vbpid(struct qbman_attr *a, u32 *vbpid); -+void qbman_bp_attr_get_icid(struct qbman_attr *a, u32 *icid, int *pl); -+void qbman_bp_attr_get_bpscn_addr(struct qbman_attr *a, u64 *bpscn_addr); -+void qbman_bp_attr_get_bpscn_ctx(struct qbman_attr *a, u64 *bpscn_ctx); -+void qbman_bp_attr_get_hw_targ(struct qbman_attr *a, u32 *hw_targ); -+int qbman_bp_info_has_free_bufs(struct qbman_attr *a); -+int qbman_bp_info_is_depleted(struct qbman_attr *a); -+int qbman_bp_info_is_surplus(struct qbman_attr *a); -+u32 qbman_bp_info_num_free_bufs(struct qbman_attr *a); -+u32 qbman_bp_info_hdptr(struct qbman_attr *a); -+u32 qbman_bp_info_sdcnt(struct qbman_attr *a); -+u32 qbman_bp_info_hdcnt(struct qbman_attr *a); -+u32 qbman_bp_info_sscnt(struct qbman_attr *a); -+ -+/* FQ query function for programmable fields */ -+int qbman_fq_query(struct qbman_swp *s, u32 fqid, -+ struct qbman_attr *desc); -+void qbman_fq_attr_get_fqctrl(struct qbman_attr *d, u32 *fqctrl); -+void qbman_fq_attr_get_cgrid(struct qbman_attr *d, u32 *cgrid); -+void qbman_fq_attr_get_destwq(struct qbman_attr *d, u32 *destwq); -+void qbman_fq_attr_get_icscred(struct qbman_attr *d, u32 *icscred); -+void qbman_fq_attr_get_tdthresh(struct qbman_attr *d, u32 *tdthresh); -+void qbman_fq_attr_get_oa(struct qbman_attr *d, -+ int *oa_ics, int *oa_cgr, int32_t *oa_len); -+void qbman_fq_attr_get_mctl(struct qbman_attr *d, -+ int *bdi, int *ff, int *va, int *ps); -+void qbman_fq_attr_get_ctx(struct qbman_attr *d, u32 *hi, u32 *lo); -+void qbman_fq_attr_get_icid(struct qbman_attr *d, u32 *icid, int *pl); -+void qbman_fq_attr_get_vfqid(struct qbman_attr *d, u32 *vfqid); -+void qbman_fq_attr_get_erfqid(struct qbman_attr *d, u32 *erfqid); -+ -+/* FQ query command for non-programmable fields*/ -+enum qbman_fq_schedstate_e { -+ qbman_fq_schedstate_oos = 0, -+ qbman_fq_schedstate_retired, -+ qbman_fq_schedstate_tentatively_scheduled, -+ qbman_fq_schedstate_truly_scheduled, -+ qbman_fq_schedstate_parked, -+ qbman_fq_schedstate_held_active, -+}; ++ struct qbman_bp_query_rslt *r); + -+int qbman_fq_query_state(struct qbman_swp *s, u32 fqid, -+ struct qbman_attr *state); -+u32 qbman_fq_state_schedstate(const struct qbman_attr *state); -+int qbman_fq_state_force_eligible(const struct qbman_attr *state); -+int qbman_fq_state_xoff(const struct qbman_attr *state); -+int qbman_fq_state_retirement_pending(const struct qbman_attr *state); -+int qbman_fq_state_overflow_error(const struct qbman_attr *state); -+u32 qbman_fq_state_frame_count(const struct qbman_attr *state); -+u32 qbman_fq_state_byte_count(const struct qbman_attr *state); -+ -+/* CGR query */ -+int qbman_cgr_query(struct qbman_swp *s, u32 cgid, -+ struct qbman_attr *attr); -+void qbman_cgr_attr_get_ctl1(struct qbman_attr *d, int *cscn_wq_en_enter, -+ int *cscn_wq_en_exit, int *cscn_wq_icd); -+void qbman_cgr_attr_get_mode(struct qbman_attr *d, u32 *mode, -+ int *rej_cnt_mode, int *cscn_bdi); -+void qbman_cgr_attr_get_ctl2(struct qbman_attr *d, int *cscn_wr_en_enter, -+ int *cscn_wr_en_exit, int *cg_wr_ae, -+ int *cscn_dcp_en, int *cg_wr_va); -+void qbman_cgr_attr_get_iwc(struct qbman_attr *d, int *i_cnt_wr_en, -+ u32 *i_cnt_wr_bnd); -+void qbman_cgr_attr_get_tdc(struct qbman_attr *d, int *td_en); -+void qbman_cgr_attr_get_cs_thres(struct qbman_attr *d, u32 *cs_thres); -+void qbman_cgr_attr_get_cs_thres_x(struct qbman_attr *d, -+ u32 *cs_thres_x); -+void qbman_cgr_attr_get_td_thres(struct qbman_attr *d, u32 *td_thres); -+void qbman_cgr_attr_get_cscn_tdcp(struct qbman_attr *d, u32 *cscn_tdcp); -+void qbman_cgr_attr_get_cscn_wqid(struct qbman_attr *d, u32 *cscn_wqid); -+void qbman_cgr_attr_get_cscn_vcgid(struct qbman_attr *d, -+ u32 *cscn_vcgid); -+void qbman_cgr_attr_get_cg_icid(struct qbman_attr *d, u32 *icid, -+ int *pl); -+void qbman_cgr_attr_get_cg_wr_addr(struct qbman_attr *d, -+ u64 *cg_wr_addr); -+void qbman_cgr_attr_get_cscn_ctx(struct qbman_attr *d, u64 *cscn_ctx); -+void qbman_cgr_attr_wred_get_edp(struct qbman_attr *d, u32 idx, -+ int *edp); -+void qbman_cgr_attr_wred_dp_decompose(u32 dp, u64 *minth, -+ u64 *maxth, u8 *maxp); -+void qbman_cgr_attr_wred_get_parm_dp(struct qbman_attr *d, u32 idx, -+ u32 *dp); -+ -+/* CGR/CCGR/CQ statistics query */ -+int qbman_cgr_reject_statistics(struct qbman_swp *s, u32 cgid, int clear, -+ u64 *frame_cnt, u64 *byte_cnt); -+int qbman_ccgr_reject_statistics(struct qbman_swp *s, u32 cgid, int clear, -+ u64 *frame_cnt, u64 *byte_cnt); -+int qbman_cq_dequeue_statistics(struct qbman_swp *s, u32 cgid, int clear, -+ u64 *frame_cnt, u64 *byte_cnt); ---- /dev/null -+++ b/drivers/staging/fsl-mc/bus/dpio/qbman_private.h -@@ -0,0 +1,171 @@ -+/* Copyright (C) 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. -+ */ ++u32 qbman_bp_info_num_free_bufs(struct qbman_bp_query_rslt *a); + -+/* Perform extra checking */ -+#define QBMAN_CHECKING -+ -+/* To maximise the amount of logic that is common between the Linux driver and -+ * other targets (such as the embedded MC firmware), we pivot here between the -+ * inclusion of two platform-specific headers. -+ * -+ * The first, qbman_sys_decl.h, includes any and all required system headers as -+ * well as providing any definitions for the purposes of compatibility. The -+ * second, qbman_sys.h, is where platform-specific routines go. -+ * -+ * The point of the split is that the platform-independent code (including this -+ * header) may depend on platform-specific declarations, yet other -+ * platform-specific routines may depend on platform-independent definitions. -+ */ -+ -+#define QMAN_REV_4000 0x04000000 -+#define QMAN_REV_4100 0x04010000 -+#define QMAN_REV_4101 0x04010001 -+ -+/* When things go wrong, it is a convenient trick to insert a few FOO() -+ * statements in the code to trace progress. TODO: remove this once we are -+ * hacking the code less actively. -+ */ -+#define FOO() fsl_os_print("FOO: %s:%d\n", __FILE__, __LINE__) -+ -+/* Any time there is a register interface which we poll on, this provides a -+ * "break after x iterations" scheme for it. It's handy for debugging, eg. -+ * where you don't want millions of lines of log output from a polling loop -+ * that won't, because such things tend to drown out the earlier log output -+ * that might explain what caused the problem. (NB: put ";" after each macro!) -+ * TODO: we should probably remove this once we're done sanitising the -+ * simulator... -+ */ -+#define DBG_POLL_START(loopvar) (loopvar = 1000) -+#define DBG_POLL_CHECK(loopvar) \ -+ do {if (!((loopvar)--)) WARN_ON(1); } while (0) -+ -+/* For CCSR or portal-CINH registers that contain fields at arbitrary offsets -+ * and widths, these macro-generated encode/decode/isolate/remove inlines can -+ * be used. -+ * -+ * Eg. to "d"ecode a 14-bit field out of a register (into a "u16" type), -+ * where the field is located 3 bits "up" from the least-significant bit of the -+ * register (ie. the field location within the 32-bit register corresponds to a -+ * mask of 0x0001fff8), you would do; -+ * u16 field = d32_u16(3, 14, reg_value); -+ * -+ * Or to "e"ncode a 1-bit boolean value (input type is "int", zero is FALSE, -+ * non-zero is TRUE, so must convert all non-zero inputs to 1, hence the "!!" -+ * operator) into a register at bit location 0x00080000 (19 bits "in" from the -+ * LS bit), do; -+ * reg_value |= e32_int(19, 1, !!field); -+ * -+ * If you wish to read-modify-write a register, such that you leave the 14-bit -+ * field as-is but have all other fields set to zero, then "i"solate the 14-bit -+ * value using; -+ * reg_value = i32_u16(3, 14, reg_value); -+ * -+ * Alternatively, you could "r"emove the 1-bit boolean field (setting it to -+ * zero) but leaving all other fields as-is; -+ * reg_val = r32_int(19, 1, reg_value); -+ * -+ */ -+#define MAKE_MASK32(width) (width == 32 ? 0xffffffff : \ -+ (u32)((1 << width) - 1)) -+#define DECLARE_CODEC32(t) \ -+static inline u32 e32_##t(u32 lsoffset, u32 width, t val) \ -+{ \ -+ WARN_ON(width > (sizeof(t) * 8)); \ -+ return ((u32)val & MAKE_MASK32(width)) << lsoffset; \ -+} \ -+static inline t d32_##t(u32 lsoffset, u32 width, u32 val) \ -+{ \ -+ WARN_ON(width > (sizeof(t) * 8)); \ -+ return (t)((val >> lsoffset) & MAKE_MASK32(width)); \ -+} \ -+static inline u32 i32_##t(u32 lsoffset, u32 width, \ -+ u32 val) \ -+{ \ -+ WARN_ON(width > (sizeof(t) * 8)); \ -+ return e32_##t(lsoffset, width, d32_##t(lsoffset, width, val)); \ -+} \ -+static inline u32 r32_##t(u32 lsoffset, u32 width, \ -+ u32 val) \ -+{ \ -+ WARN_ON(width > (sizeof(t) * 8)); \ -+ return ~(MAKE_MASK32(width) << lsoffset) & val; \ -+} -+DECLARE_CODEC32(u32) -+DECLARE_CODEC32(u16) -+DECLARE_CODEC32(u8) -+DECLARE_CODEC32(int) -+ -+ /*********************/ -+ /* Debugging assists */ -+ /*********************/ -+ -+static inline void __hexdump(unsigned long start, unsigned long end, -+ unsigned long p, size_t sz, -+ const unsigned char *c) -+{ -+ while (start < end) { -+ unsigned int pos = 0; -+ char buf[64]; -+ int nl = 0; -+ -+ pos += sprintf(buf + pos, "%08lx: ", start); -+ do { -+ if ((start < p) || (start >= (p + sz))) -+ pos += sprintf(buf + pos, ".."); -+ else -+ pos += sprintf(buf + pos, "%02x", *(c++)); -+ if (!(++start & 15)) { -+ buf[pos++] = '\n'; -+ nl = 1; -+ } else { -+ nl = 0; -+ if (!(start & 1)) -+ buf[pos++] = ' '; -+ if (!(start & 3)) -+ buf[pos++] = ' '; -+ } -+ } while (start & 15); -+ if (!nl) -+ buf[pos++] = '\n'; -+ buf[pos] = '\0'; -+ pr_info("%s", buf); -+ } -+} -+ -+static inline void hexdump(const void *ptr, size_t sz) -+{ -+ unsigned long p = (unsigned long)ptr; -+ unsigned long start = p & ~15ul; -+ unsigned long end = (p + sz + 15) & ~15ul; -+ const unsigned char *c = ptr; -+ -+ __hexdump(start, end, p, sz, c); -+} ++#endif /* __FSL_QBMAN_PORTAL_H */ --- a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h -+++ b/drivers/staging/fsl-mc/bus/dpmcp-cmd.h -@@ -1,4 +1,5 @@ ++++ /dev/null +@@ -1,140 +0,0 @@ -/* Copyright 2013-2016 Freescale Semiconductor Inc. -+/* -+ * Copyright 2013-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: -@@ -11,7 +12,6 @@ - * names of any contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * -- * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") as published by the Free Software - * Foundation, either version 2 of that License or (at your option) any -@@ -33,108 +33,24 @@ - #define _FSL_DPMCP_CMD_H - - /* Minimal supported DPMCP Version */ +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of the above-listed copyright holders nor the +- * names of any contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +- * POSSIBILITY OF SUCH DAMAGE. +- */ +-#ifndef _FSL_DPMCP_CMD_H +-#define _FSL_DPMCP_CMD_H +- +-/* Minimal supported DPMCP Version */ -#define DPMCP_MIN_VER_MAJOR 3 -#define DPMCP_MIN_VER_MINOR 0 - @@ -5626,21 +13389,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - __le32 irq_num; - __le32 type; -}; -+#define DPMCP_MIN_VER_MAJOR 3 -+#define DPMCP_MIN_VER_MINOR 0 - +- -#define DPMCP_ENABLE 0x1 -+/* Command versioning */ -+#define DPMCP_CMD_BASE_VERSION 1 -+#define DPMCP_CMD_ID_OFFSET 4 - +- -struct dpmcp_cmd_set_irq_enable { - u8 enable; - u8 pad[3]; - u8 irq_index; -}; -+#define DPMCP_CMD(id) ((id << DPMCP_CMD_ID_OFFSET) | DPMCP_CMD_BASE_VERSION) - +- -struct dpmcp_cmd_get_irq_enable { - __le32 pad; - u8 irq_index; @@ -5663,17 +13420,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> -struct dpmcp_rsp_get_irq_mask { - __le32 mask; -}; -+/* Command IDs */ -+#define DPMCP_CMDID_CLOSE DPMCP_CMD(0x800) -+#define DPMCP_CMDID_OPEN DPMCP_CMD(0x80b) -+#define DPMCP_CMDID_GET_API_VERSION DPMCP_CMD(0xa0b) - +- -struct dpmcp_cmd_get_irq_status { - __le32 status; - u8 irq_index; -}; -+#define DPMCP_CMDID_RESET DPMCP_CMD(0x005) - +- -struct dpmcp_rsp_get_irq_status { - __le32 status; -}; @@ -5685,32 +13437,118 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - /* response word 1 */ - __le16 version_major; - __le16 version_minor; -+struct dpmcp_cmd_open { -+ __le32 dpmcp_id; - }; - - #endif /* _FSL_DPMCP_CMD_H */ +-}; +- +-#endif /* _FSL_DPMCP_CMD_H */ --- a/drivers/staging/fsl-mc/bus/dpmcp.c -+++ b/drivers/staging/fsl-mc/bus/dpmcp.c -@@ -1,4 +1,5 @@ ++++ /dev/null +@@ -1,504 +0,0 @@ -/* Copyright 2013-2016 Freescale Semiconductor Inc. -+/* -+ * Copyright 2013-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: -@@ -11,7 +12,6 @@ - * names of any contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * -- * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") as published by the Free Software - * Foundation, either version 2 of that License or (at your option) any -@@ -104,76 +104,6 @@ int dpmcp_close(struct fsl_mc_io *mc_io, - } - - /** +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of the above-listed copyright holders nor the +- * names of any contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +- * POSSIBILITY OF SUCH DAMAGE. +- */ +-#include "../include/mc-sys.h" +-#include "../include/mc-cmd.h" +- +-#include "dpmcp.h" +-#include "dpmcp-cmd.h" +- +-/** +- * dpmcp_open() - Open a control session for the specified object. +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @dpmcp_id: DPMCP unique ID +- * @token: Returned token; use in subsequent API calls +- * +- * This function can be used to open a control session for an +- * already created object; an object may have been declared in +- * the DPL or by calling the dpmcp_create function. +- * This function returns a unique authentication token, +- * associated with the specific object ID and the specific MC +- * portal; this token must be used in all subsequent commands for +- * this specific object +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dpmcp_open(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- int dpmcp_id, +- u16 *token) +-{ +- struct mc_command cmd = { 0 }; +- struct dpmcp_cmd_open *cmd_params; +- int err; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPMCP_CMDID_OPEN, +- cmd_flags, 0); +- cmd_params = (struct dpmcp_cmd_open *)cmd.params; +- cmd_params->dpmcp_id = cpu_to_le32(dpmcp_id); +- +- /* send command to mc*/ +- err = mc_send_command(mc_io, &cmd); +- if (err) +- return err; +- +- /* retrieve response parameters */ +- *token = mc_cmd_hdr_read_token(&cmd); +- +- return err; +-} +- +-/** +- * dpmcp_close() - Close the control session of the object +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPMCP object +- * +- * After this function is called, no further operations are +- * allowed on the object without opening a new control session. +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dpmcp_close(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token) +-{ +- struct mc_command cmd = { 0 }; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CLOSE, +- cmd_flags, token); +- +- /* send command to mc*/ +- return mc_send_command(mc_io, &cmd); +-} +- +-/** - * dpmcp_create() - Create the DPMCP object. - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' @@ -5781,13 +13619,28 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> -} - -/** - * dpmcp_reset() - Reset the DPMCP, returns the object to initial state. - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -@@ -196,309 +126,33 @@ int dpmcp_reset(struct fsl_mc_io *mc_io, - } - - /** +- * dpmcp_reset() - Reset the DPMCP, returns the object to initial state. +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPMCP object +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dpmcp_reset(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token) +-{ +- struct mc_command cmd = { 0 }; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPMCP_CMDID_RESET, +- cmd_flags, token); +- +- /* send command to mc*/ +- return mc_send_command(mc_io, &cmd); +-} +- +-/** - * dpmcp_set_irq() - Set IRQ information for the DPMCP to trigger an interrupt. - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' @@ -5822,36 +13675,28 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> -/** - * dpmcp_get_irq() - Get IRQ information from the DPMCP. - * @mc_io: Pointer to MC portal's I/O object -+ * dpmcp_get_api_version - Get Data Path Management Command Portal API version -+ * @mc_io: Pointer to Mc portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPMCP object - * @irq_index: The interrupt index to configure - * @type: Interrupt type: 0 represents message interrupt - * type (both irq_addr and irq_val are valid) - * @irq_cfg: IRQ attributes -+ * @major_ver: Major version of Data Path Management Command Portal API -+ * @minor_ver: Minor version of Data Path Management Command Portal API - * - * Return: '0' on Success; Error code otherwise. - */ +- * +- * Return: '0' on Success; Error code otherwise. +- */ -int dpmcp_get_irq(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - int *type, - struct dpmcp_irq_cfg *irq_cfg) -+int dpmcp_get_api_version(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 *major_ver, -+ u16 *minor_ver) - { - struct mc_command cmd = { 0 }; +-{ +- struct mc_command cmd = { 0 }; - struct dpmcp_cmd_get_irq *cmd_params; - struct dpmcp_rsp_get_irq *rsp_params; - int err; - - /* prepare command */ +- int err; +- +- /* prepare command */ - cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ, - cmd_flags, token); - cmd_params = (struct dpmcp_cmd_get_irq *)cmd.params; @@ -6088,69 +13933,75 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_ATTR, - cmd_flags, token); -+ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_API_VERSION, -+ cmd_flags, 0); - +- - /* send command to mc*/ -+ /* send command to mc */ - err = mc_send_command(mc_io, &cmd); - if (err) - return err; - - /* retrieve response parameters */ +- err = mc_send_command(mc_io, &cmd); +- if (err) +- return err; +- +- /* retrieve response parameters */ - rsp_params = (struct dpmcp_rsp_get_attributes *)cmd.params; - attr->id = le32_to_cpu(rsp_params->id); - attr->version.major = le16_to_cpu(rsp_params->version_major); - attr->version.minor = le16_to_cpu(rsp_params->version_minor); -+ mc_cmd_read_api_version(&cmd, major_ver, minor_ver); - - return 0; - } +- +- return 0; +-} --- a/drivers/staging/fsl-mc/bus/dpmcp.h -+++ b/drivers/staging/fsl-mc/bus/dpmcp.h -@@ -1,4 +1,5 @@ ++++ /dev/null +@@ -1,159 +0,0 @@ -/* Copyright 2013-2015 Freescale Semiconductor Inc. -+/* -+ * Copyright 2013-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: -@@ -11,7 +12,6 @@ - * names of any contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * -- * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") as published by the Free Software - * Foundation, either version 2 of that License or (at your option) any -@@ -32,128 +32,29 @@ - #ifndef __FSL_DPMCP_H - #define __FSL_DPMCP_H - +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of the above-listed copyright holders nor the +- * names of any contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +- * POSSIBILITY OF SUCH DAMAGE. +- */ +-#ifndef __FSL_DPMCP_H +-#define __FSL_DPMCP_H +- -/* Data Path Management Command Portal API -+/* -+ * Data Path Management Command Portal API - * Contains initialization APIs and runtime control APIs for DPMCP - */ - - struct fsl_mc_io; - - int dpmcp_open(struct fsl_mc_io *mc_io, +- * Contains initialization APIs and runtime control APIs for DPMCP +- */ +- +-struct fsl_mc_io; +- +-int dpmcp_open(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, -+ u32 cmd_flags, - int dpmcp_id, +- int dpmcp_id, - uint16_t *token); - -/* Get portal ID from pool */ -#define DPMCP_GET_PORTAL_ID_FROM_POOL (-1) -+ u16 *token); - - int dpmcp_close(struct fsl_mc_io *mc_io, +- +-int dpmcp_close(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token); -+ u32 cmd_flags, -+ u16 token); - +- -/** - * struct dpmcp_cfg - Structure representing DPMCP configuration - * @portal_id: Portal ID; 'DPMCP_GET_PORTAL_ID_FROM_POOL' to get the portal ID @@ -6168,12 +14019,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> -int dpmcp_destroy(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token); -+int dpmcp_get_api_version(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 *major_ver, -+ u16 *minor_ver); - - int dpmcp_reset(struct fsl_mc_io *mc_io, +- +-int dpmcp_reset(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token); - @@ -6260,62 +14107,146 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - uint32_t cmd_flags, - uint16_t token, - struct dpmcp_attr *attr); -+ u32 cmd_flags, -+ u16 token); - - #endif /* __FSL_DPMCP_H */ +- +-#endif /* __FSL_DPMCP_H */ --- a/drivers/staging/fsl-mc/bus/dpmng-cmd.h -+++ b/drivers/staging/fsl-mc/bus/dpmng-cmd.h -@@ -12,7 +12,6 @@ - * names of any contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * -- * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") as published by the Free Software - * Foundation, either version 2 of that License or (at your option) any -@@ -41,13 +40,14 @@ - #ifndef __FSL_DPMNG_CMD_H - #define __FSL_DPMNG_CMD_H - ++++ /dev/null +@@ -1,58 +0,0 @@ +-/* +- * Copyright 2013-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 the above-listed copyright holders nor the +- * names of any contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +- * POSSIBILITY OF SUCH DAMAGE. +- */ +- +-/* +- * dpmng-cmd.h +- * +- * defines portal commands +- * +- */ +- +-#ifndef __FSL_DPMNG_CMD_H +-#define __FSL_DPMNG_CMD_H +- -/* Command IDs */ -#define DPMNG_CMDID_GET_CONT_ID 0x830 -#define DPMNG_CMDID_GET_VERSION 0x831 -+/* Command versioning */ -+#define DPMNG_CMD_BASE_VERSION 1 -+#define DPMNG_CMD_ID_OFFSET 4 - +- -struct dpmng_rsp_get_container_id { - __le32 container_id; -}; -+#define DPMNG_CMD(id) ((id << DPMNG_CMD_ID_OFFSET) | DPMNG_CMD_BASE_VERSION) -+ -+/* Command IDs */ -+#define DPMNG_CMDID_GET_VERSION DPMNG_CMD(0x831) - - struct dpmng_rsp_get_version { - __le32 revision; +- +-struct dpmng_rsp_get_version { +- __le32 revision; +- __le32 version_major; +- __le32 version_minor; +-}; +- +-#endif /* __FSL_DPMNG_CMD_H */ --- a/drivers/staging/fsl-mc/bus/dpmng.c -+++ b/drivers/staging/fsl-mc/bus/dpmng.c -@@ -1,4 +1,5 @@ ++++ /dev/null +@@ -1,107 +0,0 @@ -/* Copyright 2013-2016 Freescale Semiconductor Inc. -+/* -+ * Copyright 2013-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: -@@ -11,7 +12,6 @@ - * names of any contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * -- * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") as published by the Free Software - * Foundation, either version 2 of that License or (at your option) any -@@ -72,36 +72,3 @@ int mc_get_version(struct fsl_mc_io *mc_ - } - EXPORT_SYMBOL(mc_get_version); - +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of the above-listed copyright holders nor the +- * names of any contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +- * POSSIBILITY OF SUCH DAMAGE. +- */ +-#include "../include/mc-sys.h" +-#include "../include/mc-cmd.h" +-#include "../include/dpmng.h" +- +-#include "dpmng-cmd.h" +- +-/** +- * mc_get_version() - Retrieves the Management Complex firmware +- * version information +- * @mc_io: Pointer to opaque I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @mc_ver_info: Returned version information structure +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int mc_get_version(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- struct mc_version *mc_ver_info) +-{ +- struct mc_command cmd = { 0 }; +- struct dpmng_rsp_get_version *rsp_params; +- int err; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_VERSION, +- cmd_flags, +- 0); +- +- /* send command to mc*/ +- err = mc_send_command(mc_io, &cmd); +- if (err) +- return err; +- +- /* retrieve response parameters */ +- rsp_params = (struct dpmng_rsp_get_version *)cmd.params; +- mc_ver_info->revision = le32_to_cpu(rsp_params->revision); +- mc_ver_info->major = le32_to_cpu(rsp_params->version_major); +- mc_ver_info->minor = le32_to_cpu(rsp_params->version_minor); +- +- return 0; +-} +-EXPORT_SYMBOL(mc_get_version); +- -/** - * dpmng_get_container_id() - Get container ID associated with a given portal. - * @mc_io: Pointer to MC portal's I/O object @@ -6350,23 +14281,55 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> -} - --- a/drivers/staging/fsl-mc/bus/dprc-cmd.h -+++ b/drivers/staging/fsl-mc/bus/dprc-cmd.h -@@ -12,7 +12,6 @@ - * names of any contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * -- * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") as published by the Free Software - * Foundation, either version 2 of that License or (at your option) any -@@ -42,48 +41,39 @@ - #define _FSL_DPRC_CMD_H - - /* Minimal supported DPRC Version */ ++++ /dev/null +@@ -1,465 +0,0 @@ +-/* +- * Copyright 2013-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 the above-listed copyright holders nor the +- * names of any contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +- * POSSIBILITY OF SUCH DAMAGE. +- */ +- +-/* +- * dprc-cmd.h +- * +- * defines dprc portal commands +- * +- */ +- +-#ifndef _FSL_DPRC_CMD_H +-#define _FSL_DPRC_CMD_H +- +-/* Minimal supported DPRC Version */ -#define DPRC_MIN_VER_MAJOR 5 -+#define DPRC_MIN_VER_MAJOR 6 - #define DPRC_MIN_VER_MINOR 0 - +-#define DPRC_MIN_VER_MINOR 0 +- -/* Command IDs */ -#define DPRC_CMDID_CLOSE 0x800 -#define DPRC_CMDID_OPEN 0x805 @@ -6404,220 +14367,492 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> -#define DPRC_CMDID_DISCONNECT 0x168 -#define DPRC_CMDID_GET_POOL 0x169 -#define DPRC_CMDID_GET_POOL_COUNT 0x16A -+/* Command versioning */ -+#define DPRC_CMD_BASE_VERSION 1 -+#define DPRC_CMD_ID_OFFSET 4 - +- -#define DPRC_CMDID_GET_CONNECTION 0x16C -+#define DPRC_CMD(id) ((id << DPRC_CMD_ID_OFFSET) | DPRC_CMD_BASE_VERSION) -+ -+/* Command IDs */ -+#define DPRC_CMDID_CLOSE DPRC_CMD(0x800) -+#define DPRC_CMDID_OPEN DPRC_CMD(0x805) -+#define DPRC_CMDID_GET_API_VERSION DPRC_CMD(0xa05) -+ -+#define DPRC_CMDID_GET_ATTR DPRC_CMD(0x004) -+#define DPRC_CMDID_RESET_CONT DPRC_CMD(0x005) -+ -+#define DPRC_CMDID_SET_IRQ DPRC_CMD(0x010) -+#define DPRC_CMDID_GET_IRQ DPRC_CMD(0x011) -+#define DPRC_CMDID_SET_IRQ_ENABLE DPRC_CMD(0x012) -+#define DPRC_CMDID_GET_IRQ_ENABLE DPRC_CMD(0x013) -+#define DPRC_CMDID_SET_IRQ_MASK DPRC_CMD(0x014) -+#define DPRC_CMDID_GET_IRQ_MASK DPRC_CMD(0x015) -+#define DPRC_CMDID_GET_IRQ_STATUS DPRC_CMD(0x016) -+#define DPRC_CMDID_CLEAR_IRQ_STATUS DPRC_CMD(0x017) -+ -+#define DPRC_CMDID_GET_CONT_ID DPRC_CMD(0x830) -+#define DPRC_CMDID_GET_OBJ_COUNT DPRC_CMD(0x159) -+#define DPRC_CMDID_GET_OBJ DPRC_CMD(0x15A) -+#define DPRC_CMDID_GET_RES_COUNT DPRC_CMD(0x15B) -+#define DPRC_CMDID_GET_OBJ_REG DPRC_CMD(0x15E) -+#define DPRC_CMDID_SET_OBJ_IRQ DPRC_CMD(0x15F) -+#define DPRC_CMDID_GET_OBJ_IRQ DPRC_CMD(0x160) - - struct dprc_cmd_open { - __le32 container_id; -@@ -199,9 +189,6 @@ struct dprc_rsp_get_attributes { - /* response word 1 */ - __le32 options; - __le32 portal_id; +- +-struct dprc_cmd_open { +- __le32 container_id; +-}; +- +-struct dprc_cmd_create_container { +- /* cmd word 0 */ +- __le32 options; +- __le16 icid; +- __le16 pad0; +- /* cmd word 1 */ +- __le32 pad1; +- __le32 portal_id; +- /* cmd words 2-3 */ +- u8 label[16]; +-}; +- +-struct dprc_rsp_create_container { +- /* response word 0 */ +- __le64 pad0; +- /* response word 1 */ +- __le32 child_container_id; +- __le32 pad1; +- /* response word 2 */ +- __le64 child_portal_addr; +-}; +- +-struct dprc_cmd_destroy_container { +- __le32 child_container_id; +-}; +- +-struct dprc_cmd_reset_container { +- __le32 child_container_id; +-}; +- +-struct dprc_cmd_set_irq { +- /* cmd word 0 */ +- __le32 irq_val; +- u8 irq_index; +- u8 pad[3]; +- /* cmd word 1 */ +- __le64 irq_addr; +- /* cmd word 2 */ +- __le32 irq_num; +-}; +- +-struct dprc_cmd_get_irq { +- __le32 pad; +- u8 irq_index; +-}; +- +-struct dprc_rsp_get_irq { +- /* response word 0 */ +- __le32 irq_val; +- __le32 pad; +- /* response word 1 */ +- __le64 irq_addr; +- /* response word 2 */ +- __le32 irq_num; +- __le32 type; +-}; +- +-#define DPRC_ENABLE 0x1 +- +-struct dprc_cmd_set_irq_enable { +- u8 enable; +- u8 pad[3]; +- u8 irq_index; +-}; +- +-struct dprc_cmd_get_irq_enable { +- __le32 pad; +- u8 irq_index; +-}; +- +-struct dprc_rsp_get_irq_enable { +- u8 enabled; +-}; +- +-struct dprc_cmd_set_irq_mask { +- __le32 mask; +- u8 irq_index; +-}; +- +-struct dprc_cmd_get_irq_mask { +- __le32 pad; +- u8 irq_index; +-}; +- +-struct dprc_rsp_get_irq_mask { +- __le32 mask; +-}; +- +-struct dprc_cmd_get_irq_status { +- __le32 status; +- u8 irq_index; +-}; +- +-struct dprc_rsp_get_irq_status { +- __le32 status; +-}; +- +-struct dprc_cmd_clear_irq_status { +- __le32 status; +- u8 irq_index; +-}; +- +-struct dprc_rsp_get_attributes { +- /* response word 0 */ +- __le32 container_id; +- __le16 icid; +- __le16 pad; +- /* response word 1 */ +- __le32 options; +- __le32 portal_id; - /* response word 2 */ - __le16 version_major; - __le16 version_minor; - }; - - struct dprc_cmd_set_res_quota { -@@ -367,11 +354,16 @@ struct dprc_cmd_get_obj_region { - - struct dprc_rsp_get_obj_region { - /* response word 0 */ +-}; +- +-struct dprc_cmd_set_res_quota { +- /* cmd word 0 */ +- __le32 child_container_id; +- __le16 quota; +- __le16 pad; +- /* cmd words 1-2 */ +- u8 type[16]; +-}; +- +-struct dprc_cmd_get_res_quota { +- /* cmd word 0 */ +- __le32 child_container_id; +- __le32 pad; +- /* cmd word 1-2 */ +- u8 type[16]; +-}; +- +-struct dprc_rsp_get_res_quota { +- __le32 pad; +- __le16 quota; +-}; +- +-struct dprc_cmd_assign { +- /* cmd word 0 */ +- __le32 container_id; +- __le32 options; +- /* cmd word 1 */ +- __le32 num; +- __le32 id_base_align; +- /* cmd word 2-3 */ +- u8 type[16]; +-}; +- +-struct dprc_cmd_unassign { +- /* cmd word 0 */ +- __le32 child_container_id; +- __le32 options; +- /* cmd word 1 */ +- __le32 num; +- __le32 id_base_align; +- /* cmd word 2-3 */ +- u8 type[16]; +-}; +- +-struct dprc_rsp_get_pool_count { +- __le32 pool_count; +-}; +- +-struct dprc_cmd_get_pool { +- __le32 pool_index; +-}; +- +-struct dprc_rsp_get_pool { +- /* response word 0 */ - __le64 pad; -+ __le64 pad0; - /* response word 1 */ +- /* response word 1-2 */ +- u8 type[16]; +-}; +- +-struct dprc_rsp_get_obj_count { +- __le32 pad; +- __le32 obj_count; +-}; +- +-struct dprc_cmd_get_obj { +- __le32 obj_index; +-}; +- +-struct dprc_rsp_get_obj { +- /* response word 0 */ +- __le32 pad0; +- __le32 id; +- /* response word 1 */ +- __le16 vendor; +- u8 irq_count; +- u8 region_count; +- __le32 state; +- /* response word 2 */ +- __le16 version_major; +- __le16 version_minor; +- __le16 flags; +- __le16 pad1; +- /* response word 3-4 */ +- u8 type[16]; +- /* response word 5-6 */ +- u8 label[16]; +-}; +- +-struct dprc_cmd_get_obj_desc { +- /* cmd word 0 */ +- __le32 obj_id; +- __le32 pad; +- /* cmd word 1-2 */ +- u8 type[16]; +-}; +- +-struct dprc_rsp_get_obj_desc { +- /* response word 0 */ +- __le32 pad0; +- __le32 id; +- /* response word 1 */ +- __le16 vendor; +- u8 irq_count; +- u8 region_count; +- __le32 state; +- /* response word 2 */ +- __le16 version_major; +- __le16 version_minor; +- __le16 flags; +- __le16 pad1; +- /* response word 3-4 */ +- u8 type[16]; +- /* response word 5-6 */ +- u8 label[16]; +-}; +- +-struct dprc_cmd_get_res_count { +- /* cmd word 0 */ +- __le64 pad; +- /* cmd word 1-2 */ +- u8 type[16]; +-}; +- +-struct dprc_rsp_get_res_count { +- __le32 res_count; +-}; +- +-struct dprc_cmd_get_res_ids { +- /* cmd word 0 */ +- u8 pad0[5]; +- u8 iter_status; +- __le16 pad1; +- /* cmd word 1 */ +- __le32 base_id; +- __le32 last_id; +- /* cmd word 2-3 */ +- u8 type[16]; +-}; +- +-struct dprc_rsp_get_res_ids { +- /* response word 0 */ +- u8 pad0[5]; +- u8 iter_status; +- __le16 pad1; +- /* response word 1 */ +- __le32 base_id; +- __le32 last_id; +-}; +- +-struct dprc_cmd_get_obj_region { +- /* cmd word 0 */ +- __le32 obj_id; +- __le16 pad0; +- u8 region_index; +- u8 pad1; +- /* cmd word 1-2 */ +- __le64 pad2[2]; +- /* cmd word 3-4 */ +- u8 obj_type[16]; +-}; +- +-struct dprc_rsp_get_obj_region { +- /* response word 0 */ +- __le64 pad; +- /* response word 1 */ - __le64 base_addr; -+ __le32 base_addr; -+ __le32 pad1; - /* response word 2 */ - __le32 size; -+ u8 type; -+ u8 pad2[3]; -+ /* response word 3 */ -+ __le32 flags; - }; - - struct dprc_cmd_set_obj_label { ---- a/drivers/staging/fsl-mc/bus/dprc-driver.c -+++ b/drivers/staging/fsl-mc/bus/dprc-driver.c -@@ -1,7 +1,7 @@ - /* - * Freescale data path resource container (DPRC) driver - * -- * Copyright (C) 2014 Freescale Semiconductor, Inc. -+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. - * Author: German Rivera <German.Rivera@freescale.com> - * - * This file is licensed under the terms of the GNU General Public -@@ -160,6 +160,8 @@ static void check_plugged_state_change(s - * dprc_add_new_devices - Adds devices to the logical bus for a DPRC - * - * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object -+ * @driver_override: driver override to apply to new objects found in the -+ * DPRC, or NULL, if none. - * @obj_desc_array: array of device descriptors for child devices currently - * present in the physical DPRC. - * @num_child_objects_in_mc: number of entries in obj_desc_array -@@ -169,6 +171,7 @@ static void check_plugged_state_change(s - * in the physical DPRC. - */ - static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev, -+ const char *driver_override, - struct dprc_obj_desc *obj_desc_array, - int num_child_objects_in_mc) - { -@@ -188,11 +191,12 @@ static void dprc_add_new_devices(struct - child_dev = fsl_mc_device_lookup(obj_desc, mc_bus_dev); - if (child_dev) { - check_plugged_state_change(child_dev, obj_desc); -+ put_device(&child_dev->dev); - continue; - } - - error = fsl_mc_device_add(obj_desc, NULL, &mc_bus_dev->dev, -- &child_dev); -+ driver_override, &child_dev); - if (error < 0) - continue; - } -@@ -202,6 +206,8 @@ static void dprc_add_new_devices(struct - * dprc_scan_objects - Discover objects in a DPRC - * - * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object -+ * @driver_override: driver override to apply to new objects found in the -+ * DPRC, or NULL, if none. - * @total_irq_count: total number of IRQs needed by objects in the DPRC. - * - * Detects objects added and removed from a DPRC and synchronizes the -@@ -217,6 +223,7 @@ static void dprc_add_new_devices(struct - * of the device drivers for the non-allocatable devices. - */ - int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, -+ const char *driver_override, - unsigned int *total_irq_count) - { - int num_child_objects; -@@ -297,7 +304,7 @@ int dprc_scan_objects(struct fsl_mc_devi - dprc_remove_devices(mc_bus_dev, child_obj_desc_array, - num_child_objects); - -- dprc_add_new_devices(mc_bus_dev, child_obj_desc_array, -+ dprc_add_new_devices(mc_bus_dev, driver_override, child_obj_desc_array, - num_child_objects); - - if (child_obj_desc_array) -@@ -328,7 +335,7 @@ int dprc_scan_container(struct fsl_mc_de - * Discover objects in the DPRC: - */ - mutex_lock(&mc_bus->scan_mutex); -- error = dprc_scan_objects(mc_bus_dev, &irq_count); -+ error = dprc_scan_objects(mc_bus_dev, NULL, &irq_count); - mutex_unlock(&mc_bus->scan_mutex); - if (error < 0) - goto error; -@@ -415,7 +422,7 @@ static irqreturn_t dprc_irq0_handler_thr - DPRC_IRQ_EVENT_OBJ_CREATED)) { - unsigned int irq_count; - -- error = dprc_scan_objects(mc_dev, &irq_count); -+ error = dprc_scan_objects(mc_dev, NULL, &irq_count); - if (error < 0) { - /* - * If the error is -ENXIO, we ignore it, as it indicates -@@ -505,7 +512,7 @@ static int register_dprc_irq_handler(str - dprc_irq0_handler, - dprc_irq0_handler_thread, - IRQF_NO_SUSPEND | IRQF_ONESHOT, -- "FSL MC DPRC irq0", -+ dev_name(&mc_dev->dev), - &mc_dev->dev); - if (error < 0) { - dev_err(&mc_dev->dev, -@@ -597,6 +604,7 @@ static int dprc_probe(struct fsl_mc_devi - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); - bool mc_io_created = false; - bool msi_domain_set = false; -+ u16 major_ver, minor_ver; - - if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0)) - return -EINVAL; -@@ -669,13 +677,21 @@ static int dprc_probe(struct fsl_mc_devi - goto error_cleanup_open; - } - -- if (mc_bus->dprc_attr.version.major < DPRC_MIN_VER_MAJOR || -- (mc_bus->dprc_attr.version.major == DPRC_MIN_VER_MAJOR && -- mc_bus->dprc_attr.version.minor < DPRC_MIN_VER_MINOR)) { -+ error = dprc_get_api_version(mc_dev->mc_io, 0, -+ &major_ver, -+ &minor_ver); -+ if (error < 0) { -+ dev_err(&mc_dev->dev, "dprc_get_api_version() failed: %d\n", -+ error); -+ goto error_cleanup_open; -+ } -+ -+ if (major_ver < DPRC_MIN_VER_MAJOR || -+ (major_ver == DPRC_MIN_VER_MAJOR && -+ minor_ver < DPRC_MIN_VER_MINOR)) { - dev_err(&mc_dev->dev, - "ERROR: DPRC version %d.%d not supported\n", -- mc_bus->dprc_attr.version.major, -- mc_bus->dprc_attr.version.minor); -+ major_ver, minor_ver); - error = -ENOTSUPP; - goto error_cleanup_open; - } +- /* response word 2 */ +- __le32 size; +-}; +- +-struct dprc_cmd_set_obj_label { +- /* cmd word 0 */ +- __le32 obj_id; +- __le32 pad; +- /* cmd word 1-2 */ +- u8 label[16]; +- /* cmd word 3-4 */ +- u8 obj_type[16]; +-}; +- +-struct dprc_cmd_set_obj_irq { +- /* cmd word 0 */ +- __le32 irq_val; +- u8 irq_index; +- u8 pad[3]; +- /* cmd word 1 */ +- __le64 irq_addr; +- /* cmd word 2 */ +- __le32 irq_num; +- __le32 obj_id; +- /* cmd word 3-4 */ +- u8 obj_type[16]; +-}; +- +-struct dprc_cmd_get_obj_irq { +- /* cmd word 0 */ +- __le32 obj_id; +- u8 irq_index; +- u8 pad[3]; +- /* cmd word 1-2 */ +- u8 obj_type[16]; +-}; +- +-struct dprc_rsp_get_obj_irq { +- /* response word 0 */ +- __le32 irq_val; +- __le32 pad; +- /* response word 1 */ +- __le64 irq_addr; +- /* response word 2 */ +- __le32 irq_num; +- __le32 type; +-}; +- +-struct dprc_cmd_connect { +- /* cmd word 0 */ +- __le32 ep1_id; +- __le32 ep1_interface_id; +- /* cmd word 1 */ +- __le32 ep2_id; +- __le32 ep2_interface_id; +- /* cmd word 2-3 */ +- u8 ep1_type[16]; +- /* cmd word 4 */ +- __le32 max_rate; +- __le32 committed_rate; +- /* cmd word 5-6 */ +- u8 ep2_type[16]; +-}; +- +-struct dprc_cmd_disconnect { +- /* cmd word 0 */ +- __le32 id; +- __le32 interface_id; +- /* cmd word 1-2 */ +- u8 type[16]; +-}; +- +-struct dprc_cmd_get_connection { +- /* cmd word 0 */ +- __le32 ep1_id; +- __le32 ep1_interface_id; +- /* cmd word 1-2 */ +- u8 ep1_type[16]; +-}; +- +-struct dprc_rsp_get_connection { +- /* response word 0-2 */ +- __le64 pad[3]; +- /* response word 3 */ +- __le32 ep2_id; +- __le32 ep2_interface_id; +- /* response word 4-5 */ +- u8 ep2_type[16]; +- /* response word 6 */ +- __le32 state; +-}; +- +-#endif /* _FSL_DPRC_CMD_H */ --- a/drivers/staging/fsl-mc/bus/dprc.c -+++ b/drivers/staging/fsl-mc/bus/dprc.c -@@ -1,4 +1,5 @@ ++++ /dev/null +@@ -1,1388 +0,0 @@ -/* Copyright 2013-2016 Freescale Semiconductor Inc. -+/* -+ * Copyright 2013-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: -@@ -11,7 +12,6 @@ - * names of any contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * -- * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") as published by the Free Software - * Foundation, either version 2 of that License or (at your option) any -@@ -100,93 +100,6 @@ int dprc_close(struct fsl_mc_io *mc_io, - EXPORT_SYMBOL(dprc_close); - - /** +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of the above-listed copyright holders nor the +- * names of any contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +- * POSSIBILITY OF SUCH DAMAGE. +- */ +-#include "../include/mc-sys.h" +-#include "../include/mc-cmd.h" +-#include "../include/dprc.h" +- +-#include "dprc-cmd.h" +- +-/** +- * dprc_open() - Open DPRC object for use +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @container_id: Container ID to open +- * @token: Returned token of DPRC object +- * +- * Return: '0' on Success; Error code otherwise. +- * +- * @warning Required before any operation on the object. +- */ +-int dprc_open(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- int container_id, +- u16 *token) +-{ +- struct mc_command cmd = { 0 }; +- struct dprc_cmd_open *cmd_params; +- int err; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, cmd_flags, +- 0); +- cmd_params = (struct dprc_cmd_open *)cmd.params; +- cmd_params->container_id = cpu_to_le32(container_id); +- +- /* send command to mc*/ +- err = mc_send_command(mc_io, &cmd); +- if (err) +- return err; +- +- /* retrieve response parameters */ +- *token = mc_cmd_hdr_read_token(&cmd); +- +- return 0; +-} +-EXPORT_SYMBOL(dprc_open); +- +-/** +- * dprc_close() - Close the control session of the object +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPRC object +- * +- * After this function is called, no further operations are +- * allowed on the object without opening a new control session. +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dprc_close(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token) +-{ +- struct mc_command cmd = { 0 }; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLOSE, cmd_flags, +- token); +- +- /* send command to mc*/ +- return mc_send_command(mc_io, &cmd); +-} +-EXPORT_SYMBOL(dprc_close); +- +-/** - * dprc_create_container() - Create child container - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' @@ -6705,13 +14940,384 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> -} - -/** - * dprc_reset_container - Reset child container. - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -@@ -565,279 +478,6 @@ int dprc_get_attributes(struct fsl_mc_io - attr->icid = le16_to_cpu(rsp_params->icid); - attr->options = le32_to_cpu(rsp_params->options); - attr->portal_id = le32_to_cpu(rsp_params->portal_id); +- * dprc_reset_container - Reset child container. +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPRC object +- * @child_container_id: ID of the container to reset +- * +- * In case a software context crashes or becomes non-responsive, the parent +- * may wish to reset its resources container before the software context is +- * restarted. +- * +- * This routine informs all objects assigned to the child container that the +- * container is being reset, so they may perform any cleanup operations that are +- * needed. All objects handles that were owned by the child container shall be +- * closed. +- * +- * Note that such request may be submitted even if the child software context +- * has not crashed, but the resulting object cleanup operations will not be +- * aware of that. +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dprc_reset_container(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token, +- int child_container_id) +-{ +- struct mc_command cmd = { 0 }; +- struct dprc_cmd_reset_container *cmd_params; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPRC_CMDID_RESET_CONT, +- cmd_flags, token); +- cmd_params = (struct dprc_cmd_reset_container *)cmd.params; +- cmd_params->child_container_id = cpu_to_le32(child_container_id); +- +- /* send command to mc*/ +- return mc_send_command(mc_io, &cmd); +-} +- +-/** +- * dprc_get_irq() - Get IRQ information from the DPRC. +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPRC object +- * @irq_index: The interrupt index to configure +- * @type: Interrupt type: 0 represents message interrupt +- * type (both irq_addr and irq_val are valid) +- * @irq_cfg: IRQ attributes +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dprc_get_irq(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token, +- u8 irq_index, +- int *type, +- struct dprc_irq_cfg *irq_cfg) +-{ +- struct mc_command cmd = { 0 }; +- struct dprc_cmd_get_irq *cmd_params; +- struct dprc_rsp_get_irq *rsp_params; +- int err; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ, +- cmd_flags, +- token); +- cmd_params = (struct dprc_cmd_get_irq *)cmd.params; +- cmd_params->irq_index = irq_index; +- +- /* send command to mc*/ +- err = mc_send_command(mc_io, &cmd); +- if (err) +- return err; +- +- /* retrieve response parameters */ +- rsp_params = (struct dprc_rsp_get_irq *)cmd.params; +- irq_cfg->val = le32_to_cpu(rsp_params->irq_val); +- irq_cfg->paddr = le64_to_cpu(rsp_params->irq_addr); +- irq_cfg->irq_num = le32_to_cpu(rsp_params->irq_num); +- *type = le32_to_cpu(rsp_params->type); +- +- return 0; +-} +- +-/** +- * dprc_set_irq() - Set IRQ information for the DPRC to trigger an interrupt. +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPRC object +- * @irq_index: Identifies the interrupt index to configure +- * @irq_cfg: IRQ configuration +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dprc_set_irq(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token, +- u8 irq_index, +- struct dprc_irq_cfg *irq_cfg) +-{ +- struct mc_command cmd = { 0 }; +- struct dprc_cmd_set_irq *cmd_params; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ, +- cmd_flags, +- token); +- cmd_params = (struct dprc_cmd_set_irq *)cmd.params; +- cmd_params->irq_val = cpu_to_le32(irq_cfg->val); +- cmd_params->irq_index = irq_index; +- cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr); +- cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num); +- +- /* send command to mc*/ +- return mc_send_command(mc_io, &cmd); +-} +- +-/** +- * dprc_get_irq_enable() - Get overall interrupt state. +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPRC object +- * @irq_index: The interrupt index to configure +- * @en: Returned interrupt state - enable = 1, disable = 0 +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dprc_get_irq_enable(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token, +- u8 irq_index, +- u8 *en) +-{ +- struct mc_command cmd = { 0 }; +- struct dprc_cmd_get_irq_enable *cmd_params; +- struct dprc_rsp_get_irq_enable *rsp_params; +- int err; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_ENABLE, +- cmd_flags, token); +- cmd_params = (struct dprc_cmd_get_irq_enable *)cmd.params; +- cmd_params->irq_index = irq_index; +- +- /* send command to mc*/ +- err = mc_send_command(mc_io, &cmd); +- if (err) +- return err; +- +- /* retrieve response parameters */ +- rsp_params = (struct dprc_rsp_get_irq_enable *)cmd.params; +- *en = rsp_params->enabled & DPRC_ENABLE; +- +- return 0; +-} +- +-/** +- * dprc_set_irq_enable() - Set overall interrupt state. +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPRC object +- * @irq_index: The interrupt index to configure +- * @en: Interrupt state - enable = 1, disable = 0 +- * +- * Allows GPP software to control when interrupts are generated. +- * Each interrupt can have up to 32 causes. The enable/disable control's the +- * overall interrupt state. if the interrupt is disabled no causes will cause +- * an interrupt. +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dprc_set_irq_enable(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token, +- u8 irq_index, +- u8 en) +-{ +- struct mc_command cmd = { 0 }; +- struct dprc_cmd_set_irq_enable *cmd_params; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_ENABLE, +- cmd_flags, token); +- cmd_params = (struct dprc_cmd_set_irq_enable *)cmd.params; +- cmd_params->enable = en & DPRC_ENABLE; +- cmd_params->irq_index = irq_index; +- +- /* send command to mc*/ +- return mc_send_command(mc_io, &cmd); +-} +- +-/** +- * dprc_get_irq_mask() - Get interrupt mask. +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPRC object +- * @irq_index: The interrupt index to configure +- * @mask: Returned event mask to trigger interrupt +- * +- * Every interrupt can have up to 32 causes and the interrupt model supports +- * masking/unmasking each cause independently +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dprc_get_irq_mask(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token, +- u8 irq_index, +- u32 *mask) +-{ +- struct mc_command cmd = { 0 }; +- struct dprc_cmd_get_irq_mask *cmd_params; +- struct dprc_rsp_get_irq_mask *rsp_params; +- int err; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_MASK, +- cmd_flags, token); +- cmd_params = (struct dprc_cmd_get_irq_mask *)cmd.params; +- cmd_params->irq_index = irq_index; +- +- /* send command to mc*/ +- err = mc_send_command(mc_io, &cmd); +- if (err) +- return err; +- +- /* retrieve response parameters */ +- rsp_params = (struct dprc_rsp_get_irq_mask *)cmd.params; +- *mask = le32_to_cpu(rsp_params->mask); +- +- return 0; +-} +- +-/** +- * dprc_set_irq_mask() - Set interrupt mask. +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPRC object +- * @irq_index: The interrupt index to configure +- * @mask: event mask to trigger interrupt; +- * each bit: +- * 0 = ignore event +- * 1 = consider event for asserting irq +- * +- * Every interrupt can have up to 32 causes and the interrupt model supports +- * masking/unmasking each cause independently +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dprc_set_irq_mask(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token, +- u8 irq_index, +- u32 mask) +-{ +- struct mc_command cmd = { 0 }; +- struct dprc_cmd_set_irq_mask *cmd_params; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_MASK, +- cmd_flags, token); +- cmd_params = (struct dprc_cmd_set_irq_mask *)cmd.params; +- cmd_params->mask = cpu_to_le32(mask); +- cmd_params->irq_index = irq_index; +- +- /* send command to mc*/ +- return mc_send_command(mc_io, &cmd); +-} +- +-/** +- * dprc_get_irq_status() - Get the current status of any pending interrupts. +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPRC object +- * @irq_index: The interrupt index to configure +- * @status: Returned interrupts status - one bit per cause: +- * 0 = no interrupt pending +- * 1 = interrupt pending +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dprc_get_irq_status(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token, +- u8 irq_index, +- u32 *status) +-{ +- struct mc_command cmd = { 0 }; +- struct dprc_cmd_get_irq_status *cmd_params; +- struct dprc_rsp_get_irq_status *rsp_params; +- int err; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_STATUS, +- cmd_flags, token); +- cmd_params = (struct dprc_cmd_get_irq_status *)cmd.params; +- cmd_params->status = cpu_to_le32(*status); +- cmd_params->irq_index = irq_index; +- +- /* send command to mc*/ +- err = mc_send_command(mc_io, &cmd); +- if (err) +- return err; +- +- /* retrieve response parameters */ +- rsp_params = (struct dprc_rsp_get_irq_status *)cmd.params; +- *status = le32_to_cpu(rsp_params->status); +- +- return 0; +-} +- +-/** +- * dprc_clear_irq_status() - Clear a pending interrupt's status +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPRC object +- * @irq_index: The interrupt index to configure +- * @status: bits to clear (W1C) - one bit per cause: +- * 0 = don't change +- * 1 = clear status bit +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dprc_clear_irq_status(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token, +- u8 irq_index, +- u32 status) +-{ +- struct mc_command cmd = { 0 }; +- struct dprc_cmd_clear_irq_status *cmd_params; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLEAR_IRQ_STATUS, +- cmd_flags, token); +- cmd_params = (struct dprc_cmd_clear_irq_status *)cmd.params; +- cmd_params->status = cpu_to_le32(status); +- cmd_params->irq_index = irq_index; +- +- /* send command to mc*/ +- return mc_send_command(mc_io, &cmd); +-} +- +-/** +- * dprc_get_attributes() - Obtains container attributes +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPRC object +- * @attributes Returned container attributes +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dprc_get_attributes(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token, +- struct dprc_attributes *attr) +-{ +- struct mc_command cmd = { 0 }; +- struct dprc_rsp_get_attributes *rsp_params; +- int err; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_ATTR, +- cmd_flags, +- token); +- +- /* send command to mc*/ +- err = mc_send_command(mc_io, &cmd); +- if (err) +- return err; +- +- /* retrieve response parameters */ +- rsp_params = (struct dprc_rsp_get_attributes *)cmd.params; +- attr->container_id = le32_to_cpu(rsp_params->container_id); +- attr->icid = le16_to_cpu(rsp_params->icid); +- attr->options = le32_to_cpu(rsp_params->options); +- attr->portal_id = le32_to_cpu(rsp_params->portal_id); - attr->version.major = le16_to_cpu(rsp_params->version_major); - attr->version.minor = le16_to_cpu(rsp_params->version_minor); - @@ -6985,13 +15591,102 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - rsp_params = (struct dprc_rsp_get_pool *)cmd.params; - strncpy(type, rsp_params->type, 16); - type[15] = '\0'; - - return 0; - } -@@ -934,64 +574,6 @@ int dprc_get_obj(struct fsl_mc_io *mc_io - EXPORT_SYMBOL(dprc_get_obj); - - /** +- +- return 0; +-} +- +-/** +- * dprc_get_obj_count() - Obtains the number of objects in the DPRC +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPRC object +- * @obj_count: Number of objects assigned to the DPRC +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dprc_get_obj_count(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token, +- int *obj_count) +-{ +- struct mc_command cmd = { 0 }; +- struct dprc_rsp_get_obj_count *rsp_params; +- int err; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_COUNT, +- cmd_flags, token); +- +- /* send command to mc*/ +- err = mc_send_command(mc_io, &cmd); +- if (err) +- return err; +- +- /* retrieve response parameters */ +- rsp_params = (struct dprc_rsp_get_obj_count *)cmd.params; +- *obj_count = le32_to_cpu(rsp_params->obj_count); +- +- return 0; +-} +-EXPORT_SYMBOL(dprc_get_obj_count); +- +-/** +- * dprc_get_obj() - Get general information on an object +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPRC object +- * @obj_index: Index of the object to be queried (< obj_count) +- * @obj_desc: Returns the requested object descriptor +- * +- * The object descriptors are retrieved one by one by incrementing +- * obj_index up to (not including) the value of obj_count returned +- * from dprc_get_obj_count(). dprc_get_obj_count() must +- * be called prior to dprc_get_obj(). +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dprc_get_obj(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token, +- int obj_index, +- struct dprc_obj_desc *obj_desc) +-{ +- struct mc_command cmd = { 0 }; +- struct dprc_cmd_get_obj *cmd_params; +- struct dprc_rsp_get_obj *rsp_params; +- int err; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ, +- cmd_flags, +- token); +- cmd_params = (struct dprc_cmd_get_obj *)cmd.params; +- cmd_params->obj_index = cpu_to_le32(obj_index); +- +- /* send command to mc*/ +- err = mc_send_command(mc_io, &cmd); +- if (err) +- return err; +- +- /* retrieve response parameters */ +- rsp_params = (struct dprc_rsp_get_obj *)cmd.params; +- obj_desc->id = le32_to_cpu(rsp_params->id); +- obj_desc->vendor = le16_to_cpu(rsp_params->vendor); +- obj_desc->irq_count = rsp_params->irq_count; +- obj_desc->region_count = rsp_params->region_count; +- obj_desc->state = le32_to_cpu(rsp_params->state); +- obj_desc->ver_major = le16_to_cpu(rsp_params->version_major); +- obj_desc->ver_minor = le16_to_cpu(rsp_params->version_minor); +- obj_desc->flags = le16_to_cpu(rsp_params->flags); +- strncpy(obj_desc->type, rsp_params->type, 16); +- obj_desc->type[15] = '\0'; +- strncpy(obj_desc->label, rsp_params->label, 16); +- obj_desc->label[15] = '\0'; +- return 0; +-} +-EXPORT_SYMBOL(dprc_get_obj); +- +-/** - * dprc_get_obj_desc() - Get object descriptor. - * - * @mc_io: Pointer to MC portal's I/O object @@ -7050,13 +15745,144 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> -EXPORT_SYMBOL(dprc_get_obj_desc); - -/** - * dprc_set_obj_irq() - Set IRQ information for object to trigger an interrupt. - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -@@ -1130,52 +712,6 @@ int dprc_get_res_count(struct fsl_mc_io - EXPORT_SYMBOL(dprc_get_res_count); - - /** +- * dprc_set_obj_irq() - Set IRQ information for object to trigger an interrupt. +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPRC object +- * @obj_type: Type of the object to set its IRQ +- * @obj_id: ID of the object to set its IRQ +- * @irq_index: The interrupt index to configure +- * @irq_cfg: IRQ configuration +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dprc_set_obj_irq(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token, +- char *obj_type, +- int obj_id, +- u8 irq_index, +- struct dprc_irq_cfg *irq_cfg) +-{ +- struct mc_command cmd = { 0 }; +- struct dprc_cmd_set_obj_irq *cmd_params; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_IRQ, +- cmd_flags, +- token); +- cmd_params = (struct dprc_cmd_set_obj_irq *)cmd.params; +- cmd_params->irq_val = cpu_to_le32(irq_cfg->val); +- cmd_params->irq_index = irq_index; +- cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr); +- cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num); +- cmd_params->obj_id = cpu_to_le32(obj_id); +- strncpy(cmd_params->obj_type, obj_type, 16); +- cmd_params->obj_type[15] = '\0'; +- +- /* send command to mc*/ +- return mc_send_command(mc_io, &cmd); +-} +-EXPORT_SYMBOL(dprc_set_obj_irq); +- +-/** +- * dprc_get_obj_irq() - Get IRQ information from object. +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPRC object +- * @obj_type: Type od the object to get its IRQ +- * @obj_id: ID of the object to get its IRQ +- * @irq_index: The interrupt index to configure +- * @type: Interrupt type: 0 represents message interrupt +- * type (both irq_addr and irq_val are valid) +- * @irq_cfg: The returned IRQ attributes +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dprc_get_obj_irq(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token, +- char *obj_type, +- int obj_id, +- u8 irq_index, +- int *type, +- struct dprc_irq_cfg *irq_cfg) +-{ +- struct mc_command cmd = { 0 }; +- struct dprc_cmd_get_obj_irq *cmd_params; +- struct dprc_rsp_get_obj_irq *rsp_params; +- int err; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_IRQ, +- cmd_flags, +- token); +- cmd_params = (struct dprc_cmd_get_obj_irq *)cmd.params; +- cmd_params->obj_id = cpu_to_le32(obj_id); +- cmd_params->irq_index = irq_index; +- strncpy(cmd_params->obj_type, obj_type, 16); +- cmd_params->obj_type[15] = '\0'; +- +- /* send command to mc*/ +- err = mc_send_command(mc_io, &cmd); +- if (err) +- return err; +- +- /* retrieve response parameters */ +- rsp_params = (struct dprc_rsp_get_obj_irq *)cmd.params; +- irq_cfg->val = le32_to_cpu(rsp_params->irq_val); +- irq_cfg->paddr = le64_to_cpu(rsp_params->irq_addr); +- irq_cfg->irq_num = le32_to_cpu(rsp_params->irq_num); +- *type = le32_to_cpu(rsp_params->type); +- +- return 0; +-} +-EXPORT_SYMBOL(dprc_get_obj_irq); +- +-/** +- * dprc_get_res_count() - Obtains the number of free resources that are assigned +- * to this container, by pool type +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPRC object +- * @type: pool type +- * @res_count: Returned number of free resources of the given +- * resource type that are assigned to this DPRC +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dprc_get_res_count(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token, +- char *type, +- int *res_count) +-{ +- struct mc_command cmd = { 0 }; +- struct dprc_cmd_get_res_count *cmd_params; +- struct dprc_rsp_get_res_count *rsp_params; +- int err; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_COUNT, +- cmd_flags, token); +- cmd_params = (struct dprc_cmd_get_res_count *)cmd.params; +- strncpy(cmd_params->type, type, 16); +- cmd_params->type[15] = '\0'; +- +- /* send command to mc*/ +- err = mc_send_command(mc_io, &cmd); +- if (err) +- return err; +- +- /* retrieve response parameters */ +- rsp_params = (struct dprc_rsp_get_res_count *)cmd.params; +- *res_count = le32_to_cpu(rsp_params->res_count); +- +- return 0; +-} +-EXPORT_SYMBOL(dprc_get_res_count); +- +-/** - * dprc_get_res_ids() - Obtains IDs of free resources in the container - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' @@ -7103,54 +15929,75 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> -EXPORT_SYMBOL(dprc_get_res_ids); - -/** - * dprc_get_obj_region() - Get region information for a specified object. - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -@@ -1216,160 +752,66 @@ int dprc_get_obj_region(struct fsl_mc_io - - /* retrieve response parameters */ - rsp_params = (struct dprc_rsp_get_obj_region *)cmd.params; +- * dprc_get_obj_region() - Get region information for a specified object. +- * @mc_io: Pointer to MC portal's I/O object +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @token: Token of DPRC object +- * @obj_type; Object type as returned in dprc_get_obj() +- * @obj_id: Unique object instance as returned in dprc_get_obj() +- * @region_index: The specific region to query +- * @region_desc: Returns the requested region descriptor +- * +- * Return: '0' on Success; Error code otherwise. +- */ +-int dprc_get_obj_region(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token, +- char *obj_type, +- int obj_id, +- u8 region_index, +- struct dprc_region_desc *region_desc) +-{ +- struct mc_command cmd = { 0 }; +- struct dprc_cmd_get_obj_region *cmd_params; +- struct dprc_rsp_get_obj_region *rsp_params; +- int err; +- +- /* prepare command */ +- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG, +- cmd_flags, token); +- cmd_params = (struct dprc_cmd_get_obj_region *)cmd.params; +- cmd_params->obj_id = cpu_to_le32(obj_id); +- cmd_params->region_index = region_index; +- strncpy(cmd_params->obj_type, obj_type, 16); +- cmd_params->obj_type[15] = '\0'; +- +- /* send command to mc*/ +- err = mc_send_command(mc_io, &cmd); +- if (err) +- return err; +- +- /* retrieve response parameters */ +- rsp_params = (struct dprc_rsp_get_obj_region *)cmd.params; - region_desc->base_offset = le64_to_cpu(rsp_params->base_addr); -+ region_desc->base_offset = le32_to_cpu(rsp_params->base_addr); - region_desc->size = le32_to_cpu(rsp_params->size); -+ region_desc->type = rsp_params->type; -+ region_desc->flags = le32_to_cpu(rsp_params->flags); - - return 0; - } - EXPORT_SYMBOL(dprc_get_obj_region); - - /** +- region_desc->size = le32_to_cpu(rsp_params->size); +- +- return 0; +-} +-EXPORT_SYMBOL(dprc_get_obj_region); +- +-/** - * dprc_set_obj_label() - Set object label. - * @mc_io: Pointer to MC portal's I/O object -+ * dprc_get_api_version - Get Data Path Resource Container API version -+ * @mc_io: Pointer to Mc portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' +- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPRC object - * @obj_type: Object's type - * @obj_id: Object's ID - * @label: The required label. The maximum length is 16 chars. -+ * @major_ver: Major version of Data Path Resource Container API -+ * @minor_ver: Minor version of Data Path Resource Container API - * - * Return: '0' on Success; Error code otherwise. - */ +- * +- * Return: '0' on Success; Error code otherwise. +- */ -int dprc_set_obj_label(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - char *obj_type, - int obj_id, - char *label) -+int dprc_get_api_version(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 *major_ver, -+ u16 *minor_ver) - { - struct mc_command cmd = { 0 }; +-{ +- struct mc_command cmd = { 0 }; - struct dprc_cmd_set_obj_label *cmd_params; -+ int err; - - /* prepare command */ +- +- /* prepare command */ - cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_LABEL, - cmd_flags, - token); @@ -7160,9 +16007,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - cmd_params->label[15] = '\0'; - strncpy(cmd_params->obj_type, obj_type, 16); - cmd_params->obj_type[15] = '\0'; -+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_API_VERSION, -+ cmd_flags, 0); - +- - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} @@ -7190,11 +16035,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> -{ - struct mc_command cmd = { 0 }; - struct dprc_cmd_connect *cmd_params; -+ /* send command to mc */ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; - +- - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPRC_CMDID_CONNECT, - cmd_flags, @@ -7210,27 +16051,20 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - cmd_params->committed_rate = cpu_to_le32(cfg->committed_rate); - strncpy(cmd_params->ep2_type, endpoint2->type, 16); - cmd_params->ep2_type[15] = '\0'; -+ /* retrieve response parameters */ -+ mc_cmd_read_api_version(&cmd, major_ver, minor_ver); - +- - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -+ return 0; - } - - /** +-} +- +-/** - * dprc_disconnect() - Disconnect one endpoint to remove its network connection - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPRC object - * @endpoint: Endpoint configuration parameters -+ * dprc_get_container_id - Get container ID associated with a given portal. -+ * @mc_io: Pointer to Mc portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @container_id: Requested container id - * - * Return: '0' on Success; Error code otherwise. - */ +- * +- * Return: '0' on Success; Error code otherwise. +- */ -int dprc_disconnect(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, @@ -7274,1555 +16108,100 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - const struct dprc_endpoint *endpoint1, - struct dprc_endpoint *endpoint2, - int *state) -+int dprc_get_container_id(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ int *container_id) - { - struct mc_command cmd = { 0 }; +-{ +- struct mc_command cmd = { 0 }; - struct dprc_cmd_get_connection *cmd_params; - struct dprc_rsp_get_connection *rsp_params; - int err; - - /* prepare command */ +- int err; +- +- /* prepare command */ - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONNECTION, -+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONT_ID, - cmd_flags, +- cmd_flags, - token); - cmd_params = (struct dprc_cmd_get_connection *)cmd.params; - cmd_params->ep1_id = cpu_to_le32(endpoint1->id); - cmd_params->ep1_interface_id = cpu_to_le32(endpoint1->if_id); - strncpy(cmd_params->ep1_type, endpoint1->type, 16); - cmd_params->ep1_type[15] = '\0'; -+ 0); - - /* send command to mc*/ - err = mc_send_command(mc_io, &cmd); -@@ -1377,12 +819,7 @@ int dprc_get_connection(struct fsl_mc_io - return err; - - /* retrieve response parameters */ +- +- /* send command to mc*/ +- err = mc_send_command(mc_io, &cmd); +- if (err) +- return err; +- +- /* retrieve response parameters */ - rsp_params = (struct dprc_rsp_get_connection *)cmd.params; - endpoint2->id = le32_to_cpu(rsp_params->ep2_id); - endpoint2->if_id = le32_to_cpu(rsp_params->ep2_interface_id); - strncpy(endpoint2->type, rsp_params->ep2_type, 16); - endpoint2->type[15] = '\0'; - *state = le32_to_cpu(rsp_params->state); -+ *container_id = (int)mc_cmd_read_object_id(&cmd); - - return 0; - } ---- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c -+++ b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c -@@ -1,7 +1,7 @@ - /* -- * Freescale MC object device allocator driver -+ * fsl-mc object allocator driver - * -- * Copyright (C) 2013 Freescale Semiconductor, Inc. -+ * Copyright (C) 2013-2016 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 -@@ -12,9 +12,9 @@ - #include <linux/msi.h> - #include "../include/mc-bus.h" - #include "../include/mc-sys.h" --#include "../include/dpbp-cmd.h" --#include "../include/dpcon-cmd.h" - -+#include "dpbp-cmd.h" -+#include "dpcon-cmd.h" - #include "fsl-mc-private.h" - - #define FSL_MC_IS_ALLOCATABLE(_obj_type) \ -@@ -23,15 +23,12 @@ - strcmp(_obj_type, "dpcon") == 0) - - /** -- * fsl_mc_resource_pool_add_device - add allocatable device to a resource -- * pool of a given MC bus -+ * fsl_mc_resource_pool_add_device - add allocatable object to a resource -+ * pool of a given fsl-mc bus - * -- * @mc_bus: pointer to the MC bus -- * @pool_type: MC bus pool type -- * @mc_dev: Pointer to allocatable MC object device +- +- return 0; +-} +--- a/drivers/staging/fsl-mc/bus/fsl-mc-private.h ++++ /dev/null +@@ -1,52 +0,0 @@ +-/* +- * Freescale Management Complex (MC) bus private declarations - * -- * It adds an allocatable MC object device to a container's resource pool of -- * the given resource type -+ * @mc_bus: pointer to the fsl-mc bus -+ * @pool_type: pool type -+ * @mc_dev: pointer to allocatable fsl-mc device - */ - static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus - *mc_bus, -@@ -95,10 +92,10 @@ out: - * fsl_mc_resource_pool_remove_device - remove an allocatable device from a - * resource pool - * -- * @mc_dev: Pointer to allocatable MC object device -+ * @mc_dev: pointer to allocatable fsl-mc device - * -- * It permanently removes an allocatable MC object device from the resource -- * pool, the device is currently in, as long as it is in the pool's free list. -+ * It permanently removes an allocatable fsl-mc device from the resource -+ * pool. It's an error if the device is in use. - */ - static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device - *mc_dev) -@@ -255,17 +252,18 @@ out_unlock: - EXPORT_SYMBOL_GPL(fsl_mc_resource_free); - - /** -- * fsl_mc_object_allocate - Allocates a MC object device of the given -- * pool type from a given MC bus -+ * fsl_mc_object_allocate - Allocates an fsl-mc object of the given -+ * pool type from a given fsl-mc bus instance - * -- * @mc_dev: MC device for which the MC object device is to be allocated -- * @pool_type: MC bus resource pool type -- * @new_mc_dev: Pointer to area where the pointer to the allocated -- * MC object device is to be returned -+ * @mc_dev: fsl-mc device which is used in conjunction with the -+ * allocated object -+ * @pool_type: pool type -+ * @new_mc_dev: pointer to area where the pointer to the allocated device -+ * is to be returned - * -- * This function allocates a MC object device from the device's parent DPRC, -- * from the corresponding MC bus' pool of allocatable MC object devices of -- * the given resource type. mc_dev cannot be a DPRC itself. -+ * Allocatable objects are always used in conjunction with some functional -+ * device. This function allocates an object of the specified type from -+ * the DPRC containing the functional device. - * - * NOTE: pool_type must be different from FSL_MC_POOL_MCP, since MC - * portals are allocated using fsl_mc_portal_allocate(), instead of -@@ -312,10 +310,9 @@ error: - EXPORT_SYMBOL_GPL(fsl_mc_object_allocate); - - /** -- * fsl_mc_object_free - Returns an allocatable MC object device to the -- * corresponding resource pool of a given MC bus. +- * Copyright (C) 2016 Freescale Semiconductor, Inc. - * -- * @mc_adev: Pointer to the MC object device -+ * fsl_mc_object_free - Returns an fsl-mc object to the resource -+ * pool where it came from. -+ * @mc_adev: Pointer to the fsl-mc device - */ - void fsl_mc_object_free(struct fsl_mc_device *mc_adev) - { -@@ -332,8 +329,14 @@ void fsl_mc_object_free(struct fsl_mc_de - EXPORT_SYMBOL_GPL(fsl_mc_object_free); - - /* -- * Initialize the interrupt pool associated with a MC bus. -- * It allocates a block of IRQs from the GIC-ITS -+ * A DPRC and the devices in the DPRC all share the same GIC-ITS device -+ * ID. A block of IRQs is pre-allocated and maintained in a pool -+ * from which devices can allocate them when needed. -+ */ -+ -+/* -+ * Initialize the interrupt pool associated with an fsl-mc bus. -+ * It allocates a block of IRQs from the GIC-ITS. - */ - int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, - unsigned int irq_count) -@@ -395,7 +398,7 @@ cleanup_msi_irqs: - EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool); - - /** -- * Teardown the interrupt pool associated with an MC bus. -+ * Teardown the interrupt pool associated with an fsl-mc bus. - * It frees the IRQs that were allocated to the pool, back to the GIC-ITS. - */ - void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus) -@@ -422,11 +425,7 @@ void fsl_mc_cleanup_irq_pool(struct fsl_ - EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool); - - /** -- * It allocates the IRQs required by a given MC object device. The -- * IRQs are allocated from the interrupt pool associated with the -- * MC bus that contains the device, if the device is not a DPRC device. -- * Otherwise, the IRQs are allocated from the interrupt pool associated -- * with the MC bus that represents the DPRC device itself. -+ * Allocate the IRQs required by a given fsl-mc device. - */ - int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev) - { -@@ -495,8 +494,7 @@ error_resource_alloc: - EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs); - - /* -- * It frees the IRQs that were allocated for a MC object device, by -- * returning them to the corresponding interrupt pool. -+ * Frees the IRQs that were allocated for an fsl-mc device. - */ - void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev) - { -@@ -605,7 +603,7 @@ static int fsl_mc_allocator_probe(struct - return error; - - dev_dbg(&mc_dev->dev, -- "Allocatable MC object device bound to fsl_mc_allocator driver"); -+ "Allocatable fsl-mc device bound to fsl_mc_allocator driver"); - return 0; - } - -@@ -627,7 +625,7 @@ static int fsl_mc_allocator_remove(struc - } - - dev_dbg(&mc_dev->dev, -- "Allocatable MC object device unbound from fsl_mc_allocator driver"); -+ "Allocatable fsl-mc device unbound from fsl_mc_allocator driver"); - return 0; - } - ---- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c -+++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c -@@ -1,7 +1,7 @@ - /* - * Freescale Management Complex (MC) bus driver - * -- * Copyright (C) 2014 Freescale Semiconductor, Inc. -+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. - * Author: German Rivera <German.Rivera@freescale.com> - * - * This file is licensed under the terms of the GNU General Public -@@ -9,6 +9,8 @@ - * warranty of any kind, whether express or implied. - */ - -+#define pr_fmt(fmt) "fsl-mc: " fmt -+ - #include <linux/module.h> - #include <linux/of_device.h> - #include <linux/of_address.h> -@@ -25,8 +27,6 @@ - #include "fsl-mc-private.h" - #include "dprc-cmd.h" - --static struct kmem_cache *mc_dev_cache; +- * 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_MC_PRIVATE_H_ +-#define _FSL_MC_PRIVATE_H_ - - /** - * Default DMA mask for devices on a fsl-mc bus - */ -@@ -34,7 +34,7 @@ static struct kmem_cache *mc_dev_cache; - - /** - * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device -- * @root_mc_bus_dev: MC object device representing the root DPRC -+ * @root_mc_bus_dev: fsl-mc device representing the root DPRC - * @num_translation_ranges: number of entries in addr_translation_ranges - * @translation_ranges: array of bus to system address translation ranges - */ -@@ -62,8 +62,8 @@ struct fsl_mc_addr_translation_range { - - /** - * fsl_mc_bus_match - device to driver matching callback -- * @dev: the MC object device structure to match against -- * @drv: the device driver to search for matching MC object device id -+ * @dev: the fsl-mc device to match against -+ * @drv: the device driver to search for matching fsl-mc object type - * structures - * - * Returns 1 on success, 0 otherwise. -@@ -75,8 +75,11 @@ static int fsl_mc_bus_match(struct devic - struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv); - bool found = false; - -- if (WARN_ON(!fsl_mc_bus_exists())) -+ /* When driver_override is set, only bind to the matching driver */ -+ if (mc_dev->driver_override) { -+ found = !strcmp(mc_dev->driver_override, mc_drv->driver.name); - goto out; -+ } - - if (!mc_drv->match_id_table) - goto out; -@@ -91,7 +94,7 @@ static int fsl_mc_bus_match(struct devic - - /* - * Traverse the match_id table of the given driver, trying to find -- * a matching for the given MC object device. -+ * a matching for the given device. - */ - for (id = mc_drv->match_id_table; id->vendor != 0x0; id++) { - if (id->vendor == mc_dev->obj_desc.vendor && -@@ -132,23 +135,141 @@ static ssize_t modalias_show(struct devi - } - static DEVICE_ATTR_RO(modalias); - -+static ssize_t rescan_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ unsigned long val; -+ unsigned int irq_count; -+ struct fsl_mc_device *root_mc_dev; -+ struct fsl_mc_bus *root_mc_bus; -+ -+ if (!fsl_mc_is_root_dprc(dev)) -+ return -EINVAL; -+ -+ root_mc_dev = to_fsl_mc_device(dev); -+ root_mc_bus = to_fsl_mc_bus(root_mc_dev); -+ -+ if (kstrtoul(buf, 0, &val) < 0) -+ return -EINVAL; -+ -+ if (val) { -+ mutex_lock(&root_mc_bus->scan_mutex); -+ dprc_scan_objects(root_mc_dev, NULL, &irq_count); -+ mutex_unlock(&root_mc_bus->scan_mutex); -+ } -+ -+ return count; -+} -+static DEVICE_ATTR_WO(rescan); -+ -+static ssize_t driver_override_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); -+ const char *driver_override, *old = mc_dev->driver_override; -+ char *cp; -+ -+ if (WARN_ON(dev->bus != &fsl_mc_bus_type)) -+ return -EINVAL; -+ -+ if (count >= (PAGE_SIZE - 1)) -+ return -EINVAL; -+ -+ driver_override = kstrndup(buf, count, GFP_KERNEL); -+ if (!driver_override) -+ return -ENOMEM; -+ -+ cp = strchr(driver_override, '\n'); -+ if (cp) -+ *cp = '\0'; -+ -+ if (strlen(driver_override)) { -+ mc_dev->driver_override = driver_override; -+ } else { -+ kfree(driver_override); -+ mc_dev->driver_override = NULL; -+ } -+ -+ kfree(old); -+ -+ return count; -+} -+ -+static ssize_t driver_override_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); -+ -+ return snprintf(buf, PAGE_SIZE, "%s\n", mc_dev->driver_override); -+} -+static DEVICE_ATTR_RW(driver_override); -+ - static struct attribute *fsl_mc_dev_attrs[] = { - &dev_attr_modalias.attr, -+ &dev_attr_rescan.attr, -+ &dev_attr_driver_override.attr, - NULL, - }; - - ATTRIBUTE_GROUPS(fsl_mc_dev); - -+static int scan_fsl_mc_bus(struct device *dev, void *data) -+{ -+ unsigned int irq_count; -+ struct fsl_mc_device *root_mc_dev; -+ struct fsl_mc_bus *root_mc_bus; -+ -+ if (fsl_mc_is_root_dprc(dev)) { -+ root_mc_dev = to_fsl_mc_device(dev); -+ root_mc_bus = to_fsl_mc_bus(root_mc_dev); -+ mutex_lock(&root_mc_bus->scan_mutex); -+ dprc_scan_objects(root_mc_dev, NULL, &irq_count); -+ mutex_unlock(&root_mc_bus->scan_mutex); -+ } -+ -+ return 0; -+} -+ -+static ssize_t bus_rescan_store(struct bus_type *bus, -+ const char *buf, size_t count) -+{ -+ unsigned long val; -+ -+ if (kstrtoul(buf, 0, &val) < 0) -+ return -EINVAL; -+ -+ if (val) -+ bus_for_each_dev(bus, NULL, NULL, scan_fsl_mc_bus); -+ -+ return count; -+} -+static BUS_ATTR(rescan, (S_IWUSR | S_IWGRP), NULL, bus_rescan_store); -+ -+static struct attribute *fsl_mc_bus_attrs[] = { -+ &bus_attr_rescan.attr, -+ NULL, -+}; -+ -+static const struct attribute_group fsl_mc_bus_group = { -+ .attrs = fsl_mc_bus_attrs, -+}; -+ -+static const struct attribute_group *fsl_mc_bus_groups[] = { -+ &fsl_mc_bus_group, -+ NULL, -+}; -+ - struct bus_type fsl_mc_bus_type = { - .name = "fsl-mc", - .match = fsl_mc_bus_match, - .uevent = fsl_mc_bus_uevent, - .dev_groups = fsl_mc_dev_groups, -+ .bus_groups = fsl_mc_bus_groups, - }; - EXPORT_SYMBOL_GPL(fsl_mc_bus_type); - --static atomic_t root_dprc_count = ATOMIC_INIT(0); +-int __must_check fsl_mc_device_add(struct dprc_obj_desc *obj_desc, +- struct fsl_mc_io *mc_io, +- struct device *parent_dev, +- struct fsl_mc_device **new_mc_dev); - - static int fsl_mc_driver_probe(struct device *dev) - { - struct fsl_mc_driver *mc_drv; -@@ -164,8 +285,7 @@ static int fsl_mc_driver_probe(struct de - - error = mc_drv->probe(mc_dev); - if (error < 0) { -- dev_err(dev, "MC object device probe callback failed: %d\n", -- error); -+ dev_err(dev, "%s failed: %d\n", __func__, error); - return error; - } - -@@ -183,9 +303,7 @@ static int fsl_mc_driver_remove(struct d - - error = mc_drv->remove(mc_dev); - if (error < 0) { -- dev_err(dev, -- "MC object device remove callback failed: %d\n", -- error); -+ dev_err(dev, "%s failed: %d\n", __func__, error); - return error; - } - -@@ -232,8 +350,6 @@ int __fsl_mc_driver_register(struct fsl_ - return error; - } - -- pr_info("MC object device driver %s registered\n", -- mc_driver->driver.name); - return 0; - } - EXPORT_SYMBOL_GPL(__fsl_mc_driver_register); -@@ -249,15 +365,6 @@ void fsl_mc_driver_unregister(struct fsl - EXPORT_SYMBOL_GPL(fsl_mc_driver_unregister); - - /** -- * fsl_mc_bus_exists - check if a root dprc exists -- */ --bool fsl_mc_bus_exists(void) --{ -- return atomic_read(&root_dprc_count) > 0; --} --EXPORT_SYMBOL_GPL(fsl_mc_bus_exists); +-void fsl_mc_device_remove(struct fsl_mc_device *mc_dev); - --/** - * fsl_mc_get_root_dprc - function to traverse to the root dprc - */ - void fsl_mc_get_root_dprc(struct device *dev, -@@ -315,21 +422,6 @@ static int get_dprc_icid(struct fsl_mc_i - return error; - } - --static int get_dprc_version(struct fsl_mc_io *mc_io, -- int container_id, u16 *major, u16 *minor) --{ -- struct dprc_attributes attr; -- int error; +-int __init dprc_driver_init(void); - -- error = get_dprc_attr(mc_io, container_id, &attr); -- if (error == 0) { -- *major = attr.version.major; -- *minor = attr.version.minor; -- } +-void dprc_driver_exit(void); - -- return error; --} +-int __init fsl_mc_allocator_driver_init(void); - - static int translate_mc_addr(struct fsl_mc_device *mc_dev, - enum dprc_region_type mc_region_type, - u64 mc_offset, phys_addr_t *phys_addr) -@@ -451,18 +543,37 @@ bool fsl_mc_is_root_dprc(struct device * - return dev == root_dprc_dev; - } - -+static void fsl_mc_device_release(struct device *dev) -+{ -+ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); -+ struct fsl_mc_bus *mc_bus = NULL; -+ -+ kfree(mc_dev->regions); -+ -+ if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) -+ mc_bus = to_fsl_mc_bus(mc_dev); -+ -+ if (mc_bus) -+ kfree(mc_bus); -+ else -+ kfree(mc_dev); -+} -+ - /** -- * Add a newly discovered MC object device to be visible in Linux -+ * Add a newly discovered fsl-mc device to be visible in Linux - */ - int fsl_mc_device_add(struct dprc_obj_desc *obj_desc, - struct fsl_mc_io *mc_io, - struct device *parent_dev, -+ const char *driver_override, - struct fsl_mc_device **new_mc_dev) - { - int error; - struct fsl_mc_device *mc_dev = NULL; - struct fsl_mc_bus *mc_bus = NULL; - struct fsl_mc_device *parent_mc_dev; -+ struct device *fsl_mc_platform_dev; -+ struct device_node *fsl_mc_platform_node; - - if (dev_is_fsl_mc(parent_dev)) - parent_mc_dev = to_fsl_mc_device(parent_dev); -@@ -473,7 +584,7 @@ int fsl_mc_device_add(struct dprc_obj_de - /* - * Allocate an MC bus device object: - */ -- mc_bus = devm_kzalloc(parent_dev, sizeof(*mc_bus), GFP_KERNEL); -+ mc_bus = kzalloc(sizeof(*mc_bus), GFP_KERNEL); - if (!mc_bus) - return -ENOMEM; - -@@ -482,16 +593,30 @@ int fsl_mc_device_add(struct dprc_obj_de - /* - * Allocate a regular fsl_mc_device object: - */ -- mc_dev = kmem_cache_zalloc(mc_dev_cache, GFP_KERNEL); -+ mc_dev = kzalloc(sizeof(*mc_dev), GFP_KERNEL); - if (!mc_dev) - return -ENOMEM; - } - - mc_dev->obj_desc = *obj_desc; - mc_dev->mc_io = mc_io; -+ -+ if (driver_override) { -+ /* -+ * We trust driver_override, so we don't need to use -+ * kstrndup() here -+ */ -+ mc_dev->driver_override = kstrdup(driver_override, GFP_KERNEL); -+ if (!mc_dev->driver_override) { -+ error = -ENOMEM; -+ goto error_cleanup_dev; -+ } -+ } -+ - device_initialize(&mc_dev->dev); - mc_dev->dev.parent = parent_dev; - mc_dev->dev.bus = &fsl_mc_bus_type; -+ mc_dev->dev.release = fsl_mc_device_release; - dev_set_name(&mc_dev->dev, "%s.%d", obj_desc->type, obj_desc->id); - - if (strcmp(obj_desc->type, "dprc") == 0) { -@@ -524,8 +649,6 @@ int fsl_mc_device_add(struct dprc_obj_de - } - - mc_io2 = mc_io; +-void fsl_mc_allocator_driver_exit(void); - -- atomic_inc(&root_dprc_count); - } - - error = get_dprc_icid(mc_io2, obj_desc->id, &mc_dev->icid); -@@ -533,8 +656,8 @@ int fsl_mc_device_add(struct dprc_obj_de - goto error_cleanup_dev; - } else { - /* -- * A non-DPRC MC object device has to be a child of another -- * MC object (specifically a DPRC object) -+ * A non-DPRC object has to be a child of a DPRC, use the -+ * parent's ICID and interrupt domain. - */ - mc_dev->icid = parent_mc_dev->icid; - mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK; -@@ -556,9 +679,14 @@ int fsl_mc_device_add(struct dprc_obj_de - goto error_cleanup_dev; - } - -- /* Objects are coherent, unless 'no shareability' flag set. */ -- if (!(obj_desc->flags & DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY)) -- arch_setup_dma_ops(&mc_dev->dev, 0, 0, NULL, true); -+ fsl_mc_platform_dev = &mc_dev->dev; -+ while (dev_is_fsl_mc(fsl_mc_platform_dev)) -+ fsl_mc_platform_dev = fsl_mc_platform_dev->parent; -+ fsl_mc_platform_node = fsl_mc_platform_dev->of_node; -+ -+ /* Set up the iommu configuration for the devices. */ -+ fsl_mc_dma_configure(mc_dev, fsl_mc_platform_node, -+ !(obj_desc->flags & DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY)); - - /* - * The device-specific probe callback will get invoked by device_add() -@@ -571,9 +699,7 @@ int fsl_mc_device_add(struct dprc_obj_de - goto error_cleanup_dev; - } - -- (void)get_device(&mc_dev->dev); -- dev_dbg(parent_dev, "Added MC object device %s\n", -- dev_name(&mc_dev->dev)); -+ dev_dbg(parent_dev, "added %s\n", dev_name(&mc_dev->dev)); - - *new_mc_dev = mc_dev; - return 0; -@@ -581,47 +707,34 @@ int fsl_mc_device_add(struct dprc_obj_de - error_cleanup_dev: - kfree(mc_dev->regions); - if (mc_bus) -- devm_kfree(parent_dev, mc_bus); -+ kfree(mc_bus); - else -- kmem_cache_free(mc_dev_cache, mc_dev); -+ kfree(mc_dev); - - return error; - } - EXPORT_SYMBOL_GPL(fsl_mc_device_add); - - /** -- * fsl_mc_device_remove - Remove a MC object device from being visible to -+ * fsl_mc_device_remove - Remove an fsl-mc device from being visible to - * Linux - * -- * @mc_dev: Pointer to a MC object device object -+ * @mc_dev: Pointer to an fsl-mc device - */ - void fsl_mc_device_remove(struct fsl_mc_device *mc_dev) - { -- struct fsl_mc_bus *mc_bus = NULL; +-int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, +- enum fsl_mc_pool_type pool_type, +- struct fsl_mc_resource +- **new_resource); - -- kfree(mc_dev->regions); -+ kfree(mc_dev->driver_override); -+ mc_dev->driver_override = NULL; - - /* - * The device-specific remove callback will get invoked by device_del() - */ - device_del(&mc_dev->dev); -- put_device(&mc_dev->dev); - -- if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) { -- mc_bus = to_fsl_mc_bus(mc_dev); +-void fsl_mc_resource_free(struct fsl_mc_resource *resource); - -- if (fsl_mc_is_root_dprc(&mc_dev->dev)) { -- if (atomic_read(&root_dprc_count) > 0) -- atomic_dec(&root_dprc_count); -- else -- WARN_ON(1); -- } -- } -+ if (strcmp(mc_dev->obj_desc.type, "dprc") != 0) -+ mc_dev->dev.iommu_fwspec = NULL; - -- if (mc_bus) -- devm_kfree(mc_dev->dev.parent, mc_bus); -- else -- kmem_cache_free(mc_dev_cache, mc_dev); -+ put_device(&mc_dev->dev); - } - EXPORT_SYMBOL_GPL(fsl_mc_device_remove); - -@@ -629,8 +742,7 @@ static int parse_mc_ranges(struct device - int *paddr_cells, - int *mc_addr_cells, - int *mc_size_cells, -- const __be32 **ranges_start, -- u8 *num_ranges) -+ const __be32 **ranges_start) - { - const __be32 *prop; - int range_tuple_cell_count; -@@ -643,8 +755,6 @@ static int parse_mc_ranges(struct device - dev_warn(dev, - "missing or empty ranges property for device tree node '%s'\n", - mc_node->name); +-int fsl_mc_msi_domain_alloc_irqs(struct device *dev, +- unsigned int irq_count); - -- *num_ranges = 0; - return 0; - } - -@@ -671,8 +781,7 @@ static int parse_mc_ranges(struct device - return -EINVAL; - } - -- *num_ranges = ranges_len / tuple_len; -- return 0; -+ return ranges_len / tuple_len; - } - - static int get_mc_addr_translation_ranges(struct device *dev, -@@ -680,7 +789,7 @@ static int get_mc_addr_translation_range - **ranges, - u8 *num_ranges) - { -- int error; -+ int ret; - int paddr_cells; - int mc_addr_cells; - int mc_size_cells; -@@ -688,16 +797,16 @@ static int get_mc_addr_translation_range - const __be32 *ranges_start; - const __be32 *cell; - -- error = parse_mc_ranges(dev, -+ ret = parse_mc_ranges(dev, - &paddr_cells, - &mc_addr_cells, - &mc_size_cells, -- &ranges_start, -- num_ranges); -- if (error < 0) -- return error; -+ &ranges_start); -+ if (ret < 0) -+ return ret; - -- if (!(*num_ranges)) { -+ *num_ranges = ret; -+ if (!ret) { - /* - * Missing or empty ranges property ("ranges;") for the - * 'fsl,qoriq-mc' node. In this case, identity mapping -@@ -749,8 +858,6 @@ static int fsl_mc_bus_probe(struct platf - struct mc_version mc_version; - struct resource res; - -- dev_info(&pdev->dev, "Root MC bus device probed"); +-void fsl_mc_msi_domain_free_irqs(struct device *dev); - - mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL); - if (!mc) - return -ENOMEM; -@@ -783,8 +890,7 @@ static int fsl_mc_bus_probe(struct platf - goto error_cleanup_mc_io; - } - -- dev_info(&pdev->dev, -- "Freescale Management Complex Firmware version: %u.%u.%u\n", -+ dev_info(&pdev->dev, "MC firmware version: %u.%u.%u\n", - mc_version.major, mc_version.minor, mc_version.revision); - - error = get_mc_addr_translation_ranges(&pdev->dev, -@@ -793,16 +899,17 @@ static int fsl_mc_bus_probe(struct platf - if (error < 0) - goto error_cleanup_mc_io; - -- error = dpmng_get_container_id(mc_io, 0, &container_id); -+ error = dprc_get_container_id(mc_io, 0, &container_id); - if (error < 0) { - dev_err(&pdev->dev, -- "dpmng_get_container_id() failed: %d\n", error); -+ "dprc_get_container_id() failed: %d\n", error); - goto error_cleanup_mc_io; - } - - memset(&obj_desc, 0, sizeof(struct dprc_obj_desc)); -- error = get_dprc_version(mc_io, container_id, -- &obj_desc.ver_major, &obj_desc.ver_minor); -+ error = dprc_get_api_version(mc_io, 0, -+ &obj_desc.ver_major, -+ &obj_desc.ver_minor); - if (error < 0) - goto error_cleanup_mc_io; - -@@ -812,7 +919,8 @@ static int fsl_mc_bus_probe(struct platf - obj_desc.irq_count = 1; - obj_desc.region_count = 0; - -- error = fsl_mc_device_add(&obj_desc, mc_io, &pdev->dev, &mc_bus_dev); -+ error = fsl_mc_device_add(&obj_desc, mc_io, &pdev->dev, NULL, -+ &mc_bus_dev); - if (error < 0) - goto error_cleanup_mc_io; - -@@ -840,7 +948,6 @@ static int fsl_mc_bus_remove(struct plat - fsl_destroy_mc_io(mc->root_mc_bus_dev->mc_io); - mc->root_mc_bus_dev->mc_io = NULL; - -- dev_info(&pdev->dev, "Root MC bus device removed"); - return 0; - } - -@@ -865,22 +972,12 @@ static int __init fsl_mc_bus_driver_init - { - int error; - -- mc_dev_cache = kmem_cache_create("fsl_mc_device", -- sizeof(struct fsl_mc_device), 0, 0, -- NULL); -- if (!mc_dev_cache) { -- pr_err("Could not create fsl_mc_device cache\n"); -- return -ENOMEM; -- } +-int __init its_fsl_mc_msi_init(void); - - error = bus_register(&fsl_mc_bus_type); - if (error < 0) { -- pr_err("fsl-mc bus type registration failed: %d\n", error); -+ pr_err("bus type registration failed: %d\n", error); - goto error_cleanup_cache; - } - -- pr_info("fsl-mc bus type registered\n"); +-void its_fsl_mc_msi_cleanup(void); - - error = platform_driver_register(&fsl_mc_bus_driver); - if (error < 0) { - pr_err("platform_driver_register() failed: %d\n", error); -@@ -914,7 +1011,6 @@ error_cleanup_bus: - bus_unregister(&fsl_mc_bus_type); - - error_cleanup_cache: -- kmem_cache_destroy(mc_dev_cache); - return error; - } - postcore_initcall(fsl_mc_bus_driver_init); ---- /dev/null -+++ b/drivers/staging/fsl-mc/bus/fsl-mc-iommu.c -@@ -0,0 +1,104 @@ -+/* -+ * Copyright 2016-17 NXP -+ * Author: Nipun Gupta <nipun.gupta@nxp.com> -+ * -+ * 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 <linux/iommu.h> -+#include <linux/of.h> -+#include <linux/of_iommu.h> -+#include "../include/mc.h" -+ -+/* Setup the IOMMU for the DPRC container */ -+static const struct iommu_ops -+*fsl_mc_iommu_configure(struct fsl_mc_device *mc_dev, -+ struct device_node *fsl_mc_platform_node) -+{ -+ struct of_phandle_args iommu_spec; -+ const struct iommu_ops *ops; -+ u32 iommu_phandle; -+ struct device_node *iommu_node; -+ const __be32 *map = NULL; -+ int iommu_cells, map_len, ret; -+ -+ map = of_get_property(fsl_mc_platform_node, "iommu-map", &map_len); -+ if (!map) -+ return NULL; -+ -+ ops = mc_dev->dev.bus->iommu_ops; -+ if (!ops || !ops->of_xlate) -+ return NULL; -+ -+ iommu_phandle = be32_to_cpup(map + 1); -+ iommu_node = of_find_node_by_phandle(iommu_phandle); -+ -+ if (of_property_read_u32(iommu_node, "#iommu-cells", &iommu_cells)) { -+ pr_err("%s: missing #iommu-cells property\n", iommu_node->name); -+ return NULL; -+ } -+ -+ /* Initialize the fwspec */ -+ ret = iommu_fwspec_init(&mc_dev->dev, &iommu_node->fwnode, ops); -+ if (ret) -+ return NULL; -+ -+ /* -+ * Fill in the required stream-id before calling the iommu's -+ * ops->xlate callback. -+ */ -+ iommu_spec.np = iommu_node; -+ iommu_spec.args[0] = mc_dev->icid; -+ iommu_spec.args_count = 1; -+ -+ ret = ops->of_xlate(&mc_dev->dev, &iommu_spec); -+ if (ret) -+ return NULL; -+ -+ of_node_put(iommu_spec.np); -+ -+ return ops; -+} -+ -+/* Set up DMA configuration for fsl-mc devices */ -+void fsl_mc_dma_configure(struct fsl_mc_device *mc_dev, -+ struct device_node *fsl_mc_platform_node, int coherent) -+{ -+ const struct iommu_ops *ops; -+ -+ ops = fsl_mc_iommu_configure(mc_dev, fsl_mc_platform_node); -+ -+ mc_dev->dev.coherent_dma_mask = DMA_BIT_MASK(48); -+ mc_dev->dev.dma_mask = &mc_dev->dev.coherent_dma_mask; -+ arch_setup_dma_ops(&mc_dev->dev, 0, -+ mc_dev->dev.coherent_dma_mask + 1, ops, coherent); -+} -+ -+/* Macro to get the container device of a MC device */ -+#define fsl_mc_cont_dev(_dev) ((to_fsl_mc_device(_dev)->flags & \ -+ FSL_MC_IS_DPRC) ? (_dev) : ((_dev)->parent)) -+ -+/* Macro to check if a device is a container device */ -+#define is_cont_dev(_dev) (to_fsl_mc_device(_dev)->flags & FSL_MC_IS_DPRC) -+ -+/* Get the IOMMU group for device on fsl-mc bus */ -+struct iommu_group *fsl_mc_device_group(struct device *dev) -+{ -+ struct device *cont_dev = fsl_mc_cont_dev(dev); -+ struct iommu_group *group; -+ -+ /* Container device is responsible for creating the iommu group */ -+ if (is_cont_dev(dev)) { -+ group = iommu_group_alloc(); -+ if (IS_ERR(group)) -+ return NULL; -+ } else { -+ get_device(cont_dev); -+ group = iommu_group_get(cont_dev); -+ put_device(cont_dev); -+ } -+ -+ return group; -+} ---- a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c -+++ b/drivers/staging/fsl-mc/bus/fsl-mc-msi.c -@@ -1,7 +1,7 @@ - /* - * Freescale Management Complex (MC) bus driver MSI support - * -- * Copyright (C) 2015 Freescale Semiconductor, Inc. -+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. - * Author: German Rivera <German.Rivera@freescale.com> - * - * This file is licensed under the terms of the GNU General Public ---- a/drivers/staging/fsl-mc/bus/fsl-mc-private.h -+++ b/drivers/staging/fsl-mc/bus/fsl-mc-private.h -@@ -10,13 +10,15 @@ - #ifndef _FSL_MC_PRIVATE_H_ - #define _FSL_MC_PRIVATE_H_ - -+#include "../include/mc.h" -+#include "../include/mc-bus.h" -+ - int __must_check fsl_mc_device_add(struct dprc_obj_desc *obj_desc, - struct fsl_mc_io *mc_io, - struct device *parent_dev, -+ const char *driver_override, - struct fsl_mc_device **new_mc_dev); - --void fsl_mc_device_remove(struct fsl_mc_device *mc_dev); +-int __must_check fsl_create_mc_io(struct device *dev, +- phys_addr_t mc_portal_phys_addr, +- u32 mc_portal_size, +- struct fsl_mc_device *dpmcp_dev, +- u32 flags, struct fsl_mc_io **new_mc_io); - - int __init dprc_driver_init(void); - - void dprc_driver_exit(void); ---- a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c -+++ b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c -@@ -1,7 +1,7 @@ - /* - * Freescale Management Complex (MC) bus driver MSI support - * -- * Copyright (C) 2015 Freescale Semiconductor, Inc. -+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. - * Author: German Rivera <German.Rivera@freescale.com> - * - * This file is licensed under the terms of the GNU General Public -@@ -20,7 +20,7 @@ - #include "fsl-mc-private.h" - - static struct irq_chip its_msi_irq_chip = { -- .name = "fsl-mc-bus-msi", -+ .name = "ITS-fMSI", - .irq_mask = irq_chip_mask_parent, - .irq_unmask = irq_chip_unmask_parent, - .irq_eoi = irq_chip_eoi_parent, -@@ -52,7 +52,7 @@ static int its_fsl_mc_msi_prepare(struct - return msi_info->ops->msi_prepare(msi_domain->parent, dev, nvec, info); - } - --static struct msi_domain_ops its_fsl_mc_msi_ops = { -+static struct msi_domain_ops its_fsl_mc_msi_ops __ro_after_init = { - .msi_prepare = its_fsl_mc_msi_prepare, - }; - -@@ -97,8 +97,8 @@ int __init its_fsl_mc_msi_init(void) - continue; - } - -- WARN_ON(mc_msi_domain-> -- host_data != &its_fsl_mc_msi_domain_info); -+ WARN_ON(mc_msi_domain->host_data != -+ &its_fsl_mc_msi_domain_info); - - pr_info("fsl-mc MSI: %s domain created\n", np->full_name); - } ---- a/drivers/staging/fsl-mc/bus/mc-io.c -+++ b/drivers/staging/fsl-mc/bus/mc-io.c -@@ -1,4 +1,5 @@ --/* Copyright 2013-2016 Freescale Semiconductor Inc. -+/* -+ * Copyright 2013-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: -@@ -11,7 +12,6 @@ - * names of any contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * -- * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") as published by the Free Software - * Foundation, either version 2 of that License or (at your option) any ---- /dev/null -+++ b/drivers/staging/fsl-mc/bus/mc-ioctl.h -@@ -0,0 +1,22 @@ -+/* -+ * Freescale Management Complex (MC) ioclt interface -+ * -+ * Copyright (C) 2014 Freescale Semiconductor, Inc. -+ * Author: Lijun Pan <Lijun.Pan@freescale.com> -+ * -+ * 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_MC_IOCTL_H_ -+#define _FSL_MC_IOCTL_H_ -+ -+#include <linux/ioctl.h> -+#include "../include/mc-sys.h" -+ -+#define RESTOOL_IOCTL_TYPE 'R' -+ -+#define RESTOOL_SEND_MC_COMMAND \ -+ _IOWR(RESTOOL_IOCTL_TYPE, 0xE0, struct mc_command) -+ -+#endif /* _FSL_MC_IOCTL_H_ */ ---- /dev/null -+++ b/drivers/staging/fsl-mc/bus/mc-restool.c -@@ -0,0 +1,405 @@ -+/* -+ * Freescale Management Complex (MC) restool driver -+ * -+ * Copyright (C) 2014 Freescale Semiconductor, Inc. -+ * Author: Lijun Pan <Lijun.Pan@freescale.com> -+ * -+ * 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/mc.h" -+#include <linux/module.h> -+#include <linux/fs.h> -+#include <linux/miscdevice.h> -+#include <linux/mm.h> -+#include <linux/slab.h> -+#include <linux/uaccess.h> -+#include <linux/mutex.h> -+#include <linux/platform_device.h> -+#include "mc-ioctl.h" -+#include "../include/mc-sys.h" -+#include "../include/mc-bus.h" -+#include "../include/mc-cmd.h" -+#include "../include/dpmng.h" -+ -+/** -+ * Maximum number of DPRCs that can be opened at the same time -+ */ -+#define MAX_DPRC_HANDLES 64 -+ -+/** -+ * restool_misc - information associated with the newly added miscdevice -+ * @misc: newly created miscdevice associated with root dprc -+ * @miscdevt: device id of this miscdevice -+ * @list: a linked list node representing this miscdevcie -+ * @static_mc_io: pointer to the static MC I/O object used by the restool -+ * @dynamic_instance_count: number of dynamically created instances -+ * @static_instance_in_use: static instance is in use or not -+ * @mutex: mutex lock to serialze the open/release operations -+ * @dev: root dprc associated with this miscdevice -+ */ -+struct restool_misc { -+ struct miscdevice misc; -+ dev_t miscdevt; -+ struct list_head list; -+ struct fsl_mc_io *static_mc_io; -+ u32 dynamic_instance_count; -+ bool static_instance_in_use; -+ struct mutex mutex; /* serialze the open/release operations */ -+ struct device *dev; -+}; -+ -+/** -+ * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device -+ * @root_mc_bus_dev: fsl-mc device representing the root DPRC -+ * @num_translation_ranges: number of entries in addr_translation_ranges -+ * @translation_ranges: array of bus to system address translation ranges -+ */ -+struct fsl_mc { -+ struct fsl_mc_device *root_mc_bus_dev; -+ u8 num_translation_ranges; -+ struct fsl_mc_addr_translation_range *translation_ranges; -+}; -+ -+/* -+ * initialize a global list to link all -+ * the miscdevice nodes (struct restool_misc) -+ */ -+static LIST_HEAD(misc_list); -+static DEFINE_MUTEX(misc_list_mutex); -+ -+static int fsl_mc_restool_dev_open(struct inode *inode, struct file *filep) -+{ -+ struct fsl_mc_device *root_mc_dev; -+ int error; -+ struct fsl_mc_io *dynamic_mc_io = NULL; -+ struct restool_misc *restool_misc = NULL; -+ struct restool_misc *restool_misc_cursor; -+ -+ mutex_lock(&misc_list_mutex); -+ -+ list_for_each_entry(restool_misc_cursor, &misc_list, list) { -+ if (restool_misc_cursor->miscdevt == inode->i_rdev) { -+ restool_misc = restool_misc_cursor; -+ break; -+ } -+ } -+ -+ mutex_unlock(&misc_list_mutex); -+ -+ if (!restool_misc) -+ return -EINVAL; -+ -+ if (WARN_ON(!restool_misc->dev)) -+ return -EINVAL; -+ -+ mutex_lock(&restool_misc->mutex); -+ -+ if (!restool_misc->static_instance_in_use) { -+ restool_misc->static_instance_in_use = true; -+ filep->private_data = restool_misc->static_mc_io; -+ } else { -+ dynamic_mc_io = kzalloc(sizeof(*dynamic_mc_io), GFP_KERNEL); -+ if (!dynamic_mc_io) { -+ error = -ENOMEM; -+ goto err_unlock; -+ } -+ -+ root_mc_dev = to_fsl_mc_device(restool_misc->dev); -+ error = fsl_mc_portal_allocate(root_mc_dev, 0, &dynamic_mc_io); -+ if (error < 0) { -+ pr_err("Not able to allocate MC portal\n"); -+ goto free_dynamic_mc_io; -+ } -+ ++restool_misc->dynamic_instance_count; -+ filep->private_data = dynamic_mc_io; -+ } -+ -+ mutex_unlock(&restool_misc->mutex); -+ -+ return 0; -+ -+free_dynamic_mc_io: -+ kfree(dynamic_mc_io); -+err_unlock: -+ mutex_unlock(&restool_misc->mutex); -+ -+ return error; -+} -+ -+static int fsl_mc_restool_dev_release(struct inode *inode, struct file *filep) -+{ -+ struct fsl_mc_io *local_mc_io = filep->private_data; -+ struct restool_misc *restool_misc = NULL; -+ struct restool_misc *restool_misc_cursor; -+ -+ if (WARN_ON(!filep->private_data)) -+ return -EINVAL; -+ -+ mutex_lock(&misc_list_mutex); -+ -+ list_for_each_entry(restool_misc_cursor, &misc_list, list) { -+ if (restool_misc_cursor->miscdevt == inode->i_rdev) { -+ restool_misc = restool_misc_cursor; -+ break; -+ } -+ } -+ -+ mutex_unlock(&misc_list_mutex); -+ -+ if (!restool_misc) -+ return -EINVAL; -+ -+ mutex_lock(&restool_misc->mutex); -+ -+ if (WARN_ON(restool_misc->dynamic_instance_count == 0 && -+ !restool_misc->static_instance_in_use)) { -+ mutex_unlock(&restool_misc->mutex); -+ return -EINVAL; -+ } -+ -+ /* Globally clean up opened/untracked handles */ -+ fsl_mc_portal_reset(local_mc_io); -+ -+ /* -+ * must check -+ * whether local_mc_io is dynamic or static instance -+ * Otherwise it will free up the reserved portal by accident -+ * or even not free up the dynamic allocated portal -+ * if 2 or more instances running concurrently -+ */ -+ if (local_mc_io == restool_misc->static_mc_io) { -+ restool_misc->static_instance_in_use = false; -+ } else { -+ fsl_mc_portal_free(local_mc_io); -+ kfree(filep->private_data); -+ --restool_misc->dynamic_instance_count; -+ } -+ -+ filep->private_data = NULL; -+ mutex_unlock(&restool_misc->mutex); -+ -+ return 0; -+} -+ -+static int restool_send_mc_command(unsigned long arg, -+ struct fsl_mc_io *local_mc_io) -+{ -+ int error; -+ struct mc_command mc_cmd; -+ -+ if (copy_from_user(&mc_cmd, (void __user *)arg, sizeof(mc_cmd))) -+ return -EFAULT; -+ -+ /* -+ * Send MC command to the MC: -+ */ -+ error = mc_send_command(local_mc_io, &mc_cmd); -+ if (error < 0) -+ return error; -+ -+ if (copy_to_user((void __user *)arg, &mc_cmd, sizeof(mc_cmd))) -+ return -EFAULT; -+ -+ return 0; -+} -+ -+static long -+fsl_mc_restool_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ int error; -+ -+ switch (cmd) { -+ case RESTOOL_SEND_MC_COMMAND: -+ error = restool_send_mc_command(arg, file->private_data); -+ break; -+ default: -+ pr_err("%s: unexpected ioctl call number\n", __func__); -+ error = -EINVAL; -+ } -+ -+ return error; -+} -+ -+static const struct file_operations fsl_mc_restool_dev_fops = { -+ .owner = THIS_MODULE, -+ .open = fsl_mc_restool_dev_open, -+ .release = fsl_mc_restool_dev_release, -+ .unlocked_ioctl = fsl_mc_restool_dev_ioctl, -+}; -+ -+static int restool_add_device_file(struct device *dev) -+{ -+ u32 name1 = 0; -+ char name2[20] = {0}; -+ int error; -+ struct fsl_mc_device *root_mc_dev; -+ struct restool_misc *restool_misc; -+ -+ if (dev->bus == &platform_bus_type && dev->driver_data) { -+ if (sscanf(dev_name(dev), "%x.%s", &name1, name2) != 2) -+ return -EINVAL; -+ -+ if (strcmp(name2, "fsl-mc") == 0) -+ pr_debug("platform's root dprc name is: %s\n", -+ dev_name(&(((struct fsl_mc *) -+ (dev->driver_data))->root_mc_bus_dev->dev))); -+ } -+ -+ if (!fsl_mc_is_root_dprc(dev)) -+ return 0; -+ -+ restool_misc = kzalloc(sizeof(*restool_misc), GFP_KERNEL); -+ if (!restool_misc) -+ return -ENOMEM; -+ -+ restool_misc->dev = dev; -+ root_mc_dev = to_fsl_mc_device(dev); -+ error = fsl_mc_portal_allocate(root_mc_dev, 0, -+ &restool_misc->static_mc_io); -+ if (error < 0) { -+ pr_err("Not able to allocate MC portal\n"); -+ goto free_restool_misc; -+ } -+ -+ restool_misc->misc.minor = MISC_DYNAMIC_MINOR; -+ restool_misc->misc.name = dev_name(dev); -+ restool_misc->misc.fops = &fsl_mc_restool_dev_fops; -+ -+ error = misc_register(&restool_misc->misc); -+ if (error < 0) { -+ pr_err("misc_register() failed: %d\n", error); -+ goto free_portal; -+ } -+ -+ restool_misc->miscdevt = restool_misc->misc.this_device->devt; -+ mutex_init(&restool_misc->mutex); -+ mutex_lock(&misc_list_mutex); -+ list_add(&restool_misc->list, &misc_list); -+ mutex_unlock(&misc_list_mutex); -+ -+ pr_info("/dev/%s driver registered\n", dev_name(dev)); -+ -+ return 0; -+ -+free_portal: -+ fsl_mc_portal_free(restool_misc->static_mc_io); -+free_restool_misc: -+ kfree(restool_misc); -+ -+ return error; -+} -+ -+static int restool_bus_notifier(struct notifier_block *nb, -+ unsigned long action, void *data) -+{ -+ int error; -+ struct device *dev = data; -+ -+ switch (action) { -+ case BUS_NOTIFY_ADD_DEVICE: -+ error = restool_add_device_file(dev); -+ if (error) -+ return error; -+ break; -+ case BUS_NOTIFY_DEL_DEVICE: -+ case BUS_NOTIFY_REMOVED_DEVICE: -+ case BUS_NOTIFY_BIND_DRIVER: -+ case BUS_NOTIFY_BOUND_DRIVER: -+ case BUS_NOTIFY_UNBIND_DRIVER: -+ case BUS_NOTIFY_UNBOUND_DRIVER: -+ break; -+ default: -+ pr_err("%s: unrecognized device action from %s\n", __func__, -+ dev_name(dev)); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int add_to_restool(struct device *dev, void *data) -+{ -+ return restool_add_device_file(dev); -+} -+ -+static int __init fsl_mc_restool_driver_init(void) -+{ -+ int error; -+ struct notifier_block *nb; -+ -+ nb = kzalloc(sizeof(*nb), GFP_KERNEL); -+ if (!nb) -+ return -ENOMEM; -+ -+ nb->notifier_call = restool_bus_notifier; -+ error = bus_register_notifier(&fsl_mc_bus_type, nb); -+ if (error) -+ goto free_nb; -+ -+ /* -+ * This driver runs after fsl-mc bus driver runs. -+ * Hence, many of the root dprcs are already attached to fsl-mc bus -+ * In order to make sure we find all the root dprcs, -+ * we need to scan the fsl_mc_bus_type. -+ */ -+ error = bus_for_each_dev(&fsl_mc_bus_type, NULL, NULL, add_to_restool); -+ if (error) { -+ bus_unregister_notifier(&fsl_mc_bus_type, nb); -+ kfree(nb); -+ pr_err("restool driver registration failure\n"); -+ return error; -+ } -+ -+ return 0; -+ -+free_nb: -+ kfree(nb); -+ return error; -+} -+ -+module_init(fsl_mc_restool_driver_init); -+ -+static void __exit fsl_mc_restool_driver_exit(void) -+{ -+ struct restool_misc *restool_misc; -+ struct restool_misc *restool_misc_tmp; -+ char name1[20] = {0}; -+ u32 name2 = 0; -+ -+ list_for_each_entry_safe(restool_misc, restool_misc_tmp, -+ &misc_list, list) { -+ if (sscanf(restool_misc->misc.name, "%4s.%u", name1, &name2) -+ != 2) -+ continue; -+ -+ pr_debug("name1=%s,name2=%u\n", name1, name2); -+ pr_debug("misc-device: %s\n", restool_misc->misc.name); -+ if (strcmp(name1, "dprc") != 0) -+ continue; -+ -+ if (WARN_ON(!restool_misc->static_mc_io)) -+ return; -+ -+ if (WARN_ON(restool_misc->dynamic_instance_count != 0)) -+ return; -+ -+ if (WARN_ON(restool_misc->static_instance_in_use)) -+ return; -+ -+ misc_deregister(&restool_misc->misc); -+ pr_info("/dev/%s driver unregistered\n", -+ restool_misc->misc.name); -+ fsl_mc_portal_free(restool_misc->static_mc_io); -+ list_del(&restool_misc->list); -+ kfree(restool_misc); -+ } -+} -+ -+module_exit(fsl_mc_restool_driver_exit); -+ -+MODULE_AUTHOR("Freescale Semiconductor Inc."); -+MODULE_DESCRIPTION("Freescale's MC restool driver"); -+MODULE_LICENSE("GPL"); ---- a/drivers/staging/fsl-mc/bus/mc-sys.c -+++ b/drivers/staging/fsl-mc/bus/mc-sys.c -@@ -1,4 +1,5 @@ --/* Copyright 2013-2014 Freescale Semiconductor Inc. -+/* -+ * Copyright 2013-2016 Freescale Semiconductor Inc. - * - * I/O services to send MC commands to the MC hardware - * -@@ -13,7 +14,6 @@ - * names of any contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * -- * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") as published by the Free Software - * Foundation, either version 2 of that License or (at your option) any -@@ -46,7 +46,7 @@ - /** - * Timeout in milliseconds to wait for the completion of an MC command - */ --#define MC_CMD_COMPLETION_TIMEOUT_MS 500 -+#define MC_CMD_COMPLETION_TIMEOUT_MS 15000 - - /* - * usleep_range() min and max values used to throttle down polling -@@ -67,7 +67,7 @@ static u16 mc_cmd_hdr_read_cmdid(struct - struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header; - u16 cmd_id = le16_to_cpu(hdr->cmd_id); - -- return (cmd_id & MC_CMD_HDR_CMDID_MASK) >> MC_CMD_HDR_CMDID_SHIFT; -+ return cmd_id; - } - - static int mc_status_to_error(enum mc_cmd_status status) -@@ -200,7 +200,7 @@ static int mc_polling_wait_preemptible(s - - if (time_after_eq(jiffies, jiffies_until_timeout)) { - dev_dbg(mc_io->dev, -- "MC command timed out (portal: %#llx, obj handle: %#x, command: %#x)\n", -+ "MC command timed out (portal: %#llx, dprc handle: %#x, command: %#x)\n", - mc_io->portal_phys_addr, - (unsigned int)mc_cmd_hdr_read_token(cmd), - (unsigned int)mc_cmd_hdr_read_cmdid(cmd)); -@@ -240,7 +240,7 @@ static int mc_polling_wait_atomic(struct - timeout_usecs -= MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS; - if (timeout_usecs == 0) { - dev_dbg(mc_io->dev, -- "MC command timed out (portal: %#llx, obj handle: %#x, command: %#x)\n", -+ "MC command timed out (portal: %#llx, dprc handle: %#x, command: %#x)\n", - mc_io->portal_phys_addr, - (unsigned int)mc_cmd_hdr_read_token(cmd), - (unsigned int)mc_cmd_hdr_read_cmdid(cmd)); -@@ -294,7 +294,7 @@ int mc_send_command(struct fsl_mc_io *mc - - if (status != MC_CMD_STATUS_OK) { - dev_dbg(mc_io->dev, -- "MC command failed: portal: %#llx, obj handle: %#x, command: %#x, status: %s (%#x)\n", -+ "MC command failed: portal: %#llx, dprc handle: %#x, command: %#x, status: %s (%#x)\n", - mc_io->portal_phys_addr, - (unsigned int)mc_cmd_hdr_read_token(cmd), - (unsigned int)mc_cmd_hdr_read_cmdid(cmd), +-void fsl_destroy_mc_io(struct fsl_mc_io *mc_io); +- +-#endif /* _FSL_MC_PRIVATE_H_ */ --- /dev/null +++ b/drivers/staging/fsl-mc/include/dpaa2-fd.h -@@ -0,0 +1,706 @@ +@@ -0,0 +1,681 @@ ++/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* + * Copyright 2014-2016 Freescale Semiconductor Inc. + * Copyright 2016 NXP + * -+ * 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_DPAA2_FD_H +#define __FSL_DPAA2_FD_H @@ -9128,7 +16507,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + */ +static inline dma_addr_t dpaa2_sg_get_addr(const struct dpaa2_sg_entry *sg) +{ -+ return le64_to_cpu((dma_addr_t)sg->addr); ++ return (dma_addr_t)le64_to_cpu(sg->addr); +} + +/** @@ -9259,8 +16638,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + */ +static inline void dpaa2_sg_set_final(struct dpaa2_sg_entry *sg, bool final) +{ -+ sg->format_offset &= cpu_to_le16(~(SG_FINAL_FLAG_MASK -+ << SG_FINAL_FLAG_SHIFT)); ++ sg->format_offset &= cpu_to_le16((~(SG_FINAL_FLAG_MASK ++ << SG_FINAL_FLAG_SHIFT)) & 0xFFFF); + sg->format_offset |= cpu_to_le16(final << SG_FINAL_FLAG_SHIFT); +} + @@ -9501,37 +16880,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#endif /* __FSL_DPAA2_FD_H */ --- /dev/null +++ b/drivers/staging/fsl-mc/include/dpaa2-global.h -@@ -0,0 +1,202 @@ +@@ -0,0 +1,177 @@ ++/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* + * Copyright 2014-2016 Freescale Semiconductor Inc. + * Copyright 2016 NXP + * -+ * 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_DPAA2_GLOBAL_H +#define __FSL_DPAA2_GLOBAL_H @@ -9706,37 +17060,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#endif /* __FSL_DPAA2_GLOBAL_H */ --- /dev/null +++ b/drivers/staging/fsl-mc/include/dpaa2-io.h -@@ -0,0 +1,190 @@ +@@ -0,0 +1,178 @@ ++/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* + * Copyright 2014-2016 Freescale Semiconductor Inc. + * Copyright 2017 NXP + * -+ * 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_DPAA2_IO_H +#define __FSL_DPAA2_IO_H @@ -9762,6 +17091,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * for dequeue. + */ + ++#define DPAA2_IO_ANY_CPU -1 ++ +/** + * struct dpaa2_io_desc - The DPIO descriptor + * @receives_notifications: Use notificaton mode. Non-zero if the DPIO @@ -9794,13 +17125,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +irqreturn_t dpaa2_io_irq(struct dpaa2_io *obj); + ++struct dpaa2_io *dpaa2_io_service_select(int cpu); ++ +/** + * struct dpaa2_io_notification_ctx - The DPIO notification context structure + * @cb: The callback to be invoked when the notification arrives + * @is_cdan: Zero for FQDAN, non-zero for CDAN + * @id: FQID or channel ID, needed for rearm -+ * @desired_cpu: The cpu on which the notifications will show up. -1 means -+ * any CPU. ++ * @desired_cpu: The cpu on which the notifications will show up. Use ++ * DPAA2_IO_ANY_CPU if don't care + * @dpio_id: The dpio index + * @qman64: The 64-bit context value shows up in the FQDAN/CDAN. + * @node: The list node @@ -9809,7 +17142,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * Used when a FQDAN/CDAN registration is made by drivers. + */ +struct dpaa2_io_notification_ctx { -+ void (*cb)(struct dpaa2_io_notification_ctx *); ++ void (*cb)(struct dpaa2_io_notification_ctx *ctx); + int is_cdan; + u32 id; + int desired_cpu; @@ -9845,13 +17178,17 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +void dpaa2_io_store_destroy(struct dpaa2_io_store *s); +struct dpaa2_dq *dpaa2_io_store_next(struct dpaa2_io_store *s, int *is_last); + -+#ifdef CONFIG_FSL_QBMAN_DEBUG -+int dpaa2_io_query_fq_count(struct dpaa2_io *d, uint32_t fqid, -+ uint32_t *fcnt, uint32_t *bcnt); -+int dpaa2_io_query_bp_count(struct dpaa2_io *d, uint32_t bpid, -+ uint32_t *num); -+#endif ++/* Order Restoration Support */ ++int dpaa2_io_service_enqueue_orp_fq(struct dpaa2_io *d, u32 fqid, ++ const struct dpaa2_fd *fd, u16 orpid, ++ u16 seqnum, int last); ++ ++int dpaa2_io_service_enqueue_orp_qd(struct dpaa2_io *d, u32 qdid, u8 prio, ++ u16 qdbin, const struct dpaa2_fd *fd, ++ u16 orpid, u16 seqnum, int last); + ++int dpaa2_io_service_orp_seqnum_drop(struct dpaa2_io *d, u16 orpid, ++ u16 seqnum); + +/***************/ +/* CSCN */ @@ -9896,6 +17233,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return ((cscn->state & DPAA2_CSCN_STATE_MASK) == DPAA2_CSCN_CONGESTED); +} + ++int dpaa2_io_query_fq_count(struct dpaa2_io *d, u32 fqid, ++ u32 *fcnt, u32 *bcnt); ++int dpaa2_io_query_bp_count(struct dpaa2_io *d, u32 bpid, ++ u32 *num); ++ +#endif /* __FSL_DPAA2_IO_H */ --- a/drivers/staging/fsl-mc/include/dpbp-cmd.h +++ /dev/null @@ -10086,28 +17428,54 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - -#endif /* _FSL_DPBP_CMD_H */ --- a/drivers/staging/fsl-mc/include/dpbp.h -+++ b/drivers/staging/fsl-mc/include/dpbp.h -@@ -1,4 +1,5 @@ ++++ /dev/null +@@ -1,220 +0,0 @@ -/* Copyright 2013-2015 Freescale Semiconductor Inc. -+/* -+ * Copyright 2013-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: -@@ -32,7 +33,8 @@ - #ifndef __FSL_DPBP_H - #define __FSL_DPBP_H - +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of the above-listed copyright holders nor the +- * names of any contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +- * POSSIBILITY OF SUCH DAMAGE. +- */ +-#ifndef __FSL_DPBP_H +-#define __FSL_DPBP_H +- -/* Data Path Buffer Pool API -+/* -+ * Data Path Buffer Pool API - * Contains initialization APIs and runtime control APIs for DPBP - */ - -@@ -44,25 +46,8 @@ int dpbp_open(struct fsl_mc_io *mc_io, - u16 *token); - - int dpbp_close(struct fsl_mc_io *mc_io, +- * Contains initialization APIs and runtime control APIs for DPBP +- */ +- +-struct fsl_mc_io; +- +-int dpbp_open(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- int dpbp_id, +- u16 *token); +- +-int dpbp_close(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token); - @@ -10127,15 +17495,25 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> -int dpbp_destroy(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token); -+ u32 cmd_flags, -+ u16 token); - - int dpbp_enable(struct fsl_mc_io *mc_io, - u32 cmd_flags, -@@ -82,139 +67,24 @@ int dpbp_reset(struct fsl_mc_io *mc_io, - u16 token); - - /** +- +-int dpbp_enable(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token); +- +-int dpbp_disable(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token); +- +-int dpbp_is_enabled(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token, +- int *en); +- +-int dpbp_reset(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token); +- +-/** - * struct dpbp_irq_cfg - IRQ configuration - * @addr: Address that must be written to signal a message-based interrupt - * @val: Value to write into irq_addr address @@ -10197,14 +17575,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - u32 status); - -/** - * struct dpbp_attr - Structure representing DPBP attributes - * @id: DPBP object ID +- * struct dpbp_attr - Structure representing DPBP attributes +- * @id: DPBP object ID - * @version: DPBP version - * @bpid: Hardware buffer pool ID; should be used as an argument in - * acquire/release operations on buffers - */ - struct dpbp_attr { - int id; +- * @bpid: Hardware buffer pool ID; should be used as an argument in +- * acquire/release operations on buffers +- */ +-struct dpbp_attr { +- int id; - /** - * struct version - Structure representing DPBP version - * @major: DPBP major version @@ -10214,9 +17592,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - u16 major; - u16 minor; - } version; - u16 bpid; - }; - +- u16 bpid; +-}; +- -int dpbp_get_attributes(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, @@ -10270,158 +17648,136 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - struct dpbp_notification_cfg *cfg); - -/** @} */ -+int dpbp_get_attributes(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ struct dpbp_attr *attr); -+ -+int dpbp_get_api_version(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 *major_ver, -+ u16 *minor_ver); - - #endif /* __FSL_DPBP_H */ ---- /dev/null -+++ b/drivers/staging/fsl-mc/include/dpcon.h -@@ -0,0 +1,115 @@ -+/* Copyright 2013-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 the above-listed copyright holders nor the -+ * names of any contributors may be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") as published by the Free Software -+ * Foundation, either version 2 of that License or (at your option) any -+ * later version. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. -+ */ -+#ifndef __FSL_DPCON_H -+#define __FSL_DPCON_H -+ -+/* Data Path Concentrator API -+ * Contains initialization APIs and runtime control APIs for DPCON -+ */ -+ -+struct fsl_mc_io; -+ -+/** General DPCON macros */ -+ -+/** -+ * Use it to disable notifications; see dpcon_set_notification() -+ */ -+#define DPCON_INVALID_DPIO_ID (int)(-1) -+ -+int dpcon_open(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ int dpcon_id, -+ u16 *token); -+ -+int dpcon_close(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token); -+ -+int dpcon_enable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token); -+ -+int dpcon_disable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token); -+ -+int dpcon_is_enabled(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ int *en); -+ -+int dpcon_reset(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token); -+ -+/** -+ * struct dpcon_attr - Structure representing DPCON attributes -+ * @id: DPCON object ID -+ * @qbman_ch_id: Channel ID to be used by dequeue operation -+ * @num_priorities: Number of priorities for the DPCON channel (1-8) -+ */ -+struct dpcon_attr { -+ int id; -+ u16 qbman_ch_id; -+ u8 num_priorities; -+}; -+ -+int dpcon_get_attributes(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ struct dpcon_attr *attr); -+ -+/** -+ * struct dpcon_notification_cfg - Structure representing notification params -+ * @dpio_id: DPIO object ID; must be configured with a notification channel; -+ * to disable notifications set it to 'DPCON_INVALID_DPIO_ID'; -+ * @priority: Priority selection within the DPIO channel; valid values -+ * are 0-7, depending on the number of priorities in that channel -+ * @user_ctx: User context value provided with each CDAN message -+ */ -+struct dpcon_notification_cfg { -+ int dpio_id; -+ u8 priority; -+ u64 user_ctx; -+}; -+ -+int dpcon_set_notification(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ struct dpcon_notification_cfg *cfg); -+ -+int dpcon_get_api_version(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 *major_ver, -+ u16 *minor_ver); -+ -+#endif /* __FSL_DPCON_H */ +- +-#endif /* __FSL_DPBP_H */ +--- a/drivers/staging/fsl-mc/include/dpcon-cmd.h ++++ /dev/null +@@ -1,62 +0,0 @@ +-/* Copyright 2013-2015 Freescale Semiconductor Inc. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of the above-listed copyright holders nor the +- * names of any contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +- * POSSIBILITY OF SUCH DAMAGE. +- */ +-#ifndef _FSL_DPCON_CMD_H +-#define _FSL_DPCON_CMD_H +- +-/* DPCON Version */ +-#define DPCON_VER_MAJOR 2 +-#define DPCON_VER_MINOR 1 +- +-/* Command IDs */ +-#define DPCON_CMDID_CLOSE 0x800 +-#define DPCON_CMDID_OPEN 0x808 +-#define DPCON_CMDID_CREATE 0x908 +-#define DPCON_CMDID_DESTROY 0x900 +- +-#define DPCON_CMDID_ENABLE 0x002 +-#define DPCON_CMDID_DISABLE 0x003 +-#define DPCON_CMDID_GET_ATTR 0x004 +-#define DPCON_CMDID_RESET 0x005 +-#define DPCON_CMDID_IS_ENABLED 0x006 +- +-#define DPCON_CMDID_SET_IRQ 0x010 +-#define DPCON_CMDID_GET_IRQ 0x011 +-#define DPCON_CMDID_SET_IRQ_ENABLE 0x012 +-#define DPCON_CMDID_GET_IRQ_ENABLE 0x013 +-#define DPCON_CMDID_SET_IRQ_MASK 0x014 +-#define DPCON_CMDID_GET_IRQ_MASK 0x015 +-#define DPCON_CMDID_GET_IRQ_STATUS 0x016 +-#define DPCON_CMDID_CLEAR_IRQ_STATUS 0x017 +- +-#define DPCON_CMDID_SET_NOTIFICATION 0x100 +- +-#endif /* _FSL_DPCON_CMD_H */ --- a/drivers/staging/fsl-mc/include/dpmng.h -+++ b/drivers/staging/fsl-mc/include/dpmng.h -@@ -1,4 +1,5 @@ ++++ /dev/null +@@ -1,69 +0,0 @@ -/* Copyright 2013-2015 Freescale Semiconductor Inc. -+/* -+ * Copyright 2013-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: -@@ -32,7 +33,8 @@ - #ifndef __FSL_DPMNG_H - #define __FSL_DPMNG_H - +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of the above-listed copyright holders nor the +- * names of any contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +- * POSSIBILITY OF SUCH DAMAGE. +- */ +-#ifndef __FSL_DPMNG_H +-#define __FSL_DPMNG_H +- -/* Management Complex General API -+/* -+ * Management Complex General API - * Contains general API for the Management Complex firmware - */ - -@@ -58,12 +60,8 @@ struct mc_version { - u32 revision; - }; - +- * Contains general API for the Management Complex firmware +- */ +- +-struct fsl_mc_io; +- +-/** +- * Management Complex firmware version information +- */ +-#define MC_VER_MAJOR 8 +-#define MC_VER_MINOR 0 +- +-/** +- * struct mc_version +- * @major: Major version number: incremented on API compatibility changes +- * @minor: Minor version number: incremented on API additions (that are +- * backward compatible); reset when major version is incremented +- * @revision: Internal revision number: incremented on implementation changes +- * and/or bug fixes that have no impact on API +- */ +-struct mc_version { +- u32 major; +- u32 minor; +- u32 revision; +-}; +- -int mc_get_version(struct fsl_mc_io *mc_io, - u32 cmd_flags, - struct mc_version *mc_ver_info); @@ -10429,14 +17785,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> -int dpmng_get_container_id(struct fsl_mc_io *mc_io, - u32 cmd_flags, - int *container_id); -+int mc_get_version(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ struct mc_version *mc_ver_info); - - #endif /* __FSL_DPMNG_H */ +- +-#endif /* __FSL_DPMNG_H */ --- /dev/null +++ b/drivers/staging/fsl-mc/include/dpopr.h -@@ -0,0 +1,110 @@ +@@ -0,0 +1,112 @@ +/* + * Copyright 2017 NXP + * @@ -10472,6 +17825,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#ifndef __FSL_DPOPR_H_ +#define __FSL_DPOPR_H_ + ++#include <linux/types.h> ++ +/* Data Path Order Restoration API + * Contains initialization APIs and runtime APIs for the Order Restoration + */ @@ -10548,26 +17903,50 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +#endif /* __FSL_DPOPR_H_ */ --- a/drivers/staging/fsl-mc/include/dprc.h -+++ b/drivers/staging/fsl-mc/include/dprc.h -@@ -1,4 +1,5 @@ ++++ /dev/null +@@ -1,544 +0,0 @@ -/* Copyright 2013-2015 Freescale Semiconductor Inc. -+/* -+ * Copyright 2013-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: -@@ -34,26 +35,13 @@ - - #include "mc-cmd.h" - +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of the above-listed copyright holders nor the +- * names of any contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +- * POSSIBILITY OF SUCH DAMAGE. +- */ +-#ifndef _FSL_DPRC_H +-#define _FSL_DPRC_H +- +-#include "mc-cmd.h" +- -/* Data Path Resource Container API -+/* -+ * Data Path Resource Container API - * Contains DPRC API for managing and querying DPAA resources - */ - - struct fsl_mc_io; - +- * Contains DPRC API for managing and querying DPAA resources +- */ +- +-struct fsl_mc_io; +- -/** - * Set this value as the icid value in dprc_cfg structure when creating a - * container, in case the ICID is not selected by the user and should be @@ -10582,13 +17961,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - */ -#define DPRC_GET_PORTAL_ID_FROM_POOL (int)(~(0)) - - int dprc_open(struct fsl_mc_io *mc_io, - u32 cmd_flags, - int container_id, -@@ -63,75 +51,6 @@ int dprc_close(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token); - +-int dprc_open(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- int container_id, +- u16 *token); +- +-int dprc_close(struct fsl_mc_io *mc_io, +- u32 cmd_flags, +- u16 token); +- -/** - * Container general options - * @@ -10658,39 +18039,45 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - u32 cmd_flags, - u16 token, - int child_container_id); - - /* IRQ */ - -@@ -139,7 +58,7 @@ int dprc_reset_container(struct fsl_mc_i - #define DPRC_IRQ_INDEX 0 - - /* Number of dprc's IRQs */ +- +-/* IRQ */ +- +-/* IRQ index */ +-#define DPRC_IRQ_INDEX 0 +- +-/* Number of dprc's IRQs */ -#define DPRC_NUM_OF_IRQS 1 -+#define DPRC_NUM_OF_IRQS 1 - - /* DPRC IRQ events */ - -@@ -151,12 +70,14 @@ int dprc_reset_container(struct fsl_mc_i - #define DPRC_IRQ_EVENT_RES_ADDED 0x00000004 - /* IRQ event - Indicates that resources removed from the container */ - #define DPRC_IRQ_EVENT_RES_REMOVED 0x00000008 +- +-/* DPRC IRQ events */ +- +-/* IRQ event - Indicates that a new object added to the container */ +-#define DPRC_IRQ_EVENT_OBJ_ADDED 0x00000001 +-/* IRQ event - Indicates that an object was removed from the container */ +-#define DPRC_IRQ_EVENT_OBJ_REMOVED 0x00000002 +-/* IRQ event - Indicates that resources added to the container */ +-#define DPRC_IRQ_EVENT_RES_ADDED 0x00000004 +-/* IRQ event - Indicates that resources removed from the container */ +-#define DPRC_IRQ_EVENT_RES_REMOVED 0x00000008 -/* IRQ event - Indicates that one of the descendant containers that opened by -+/* -+ * IRQ event - Indicates that one of the descendant containers that opened by - * this container is destroyed - */ - #define DPRC_IRQ_EVENT_CONTAINER_DESTROYED 0x00000010 - +- * this container is destroyed +- */ +-#define DPRC_IRQ_EVENT_CONTAINER_DESTROYED 0x00000010 +- -/* IRQ event - Indicates that on one of the container's opened object is -+/* -+ * IRQ event - Indicates that on one of the container's opened object is - * destroyed - */ - #define DPRC_IRQ_EVENT_OBJ_DESTROYED 0x00000020 -@@ -171,59 +92,59 @@ int dprc_reset_container(struct fsl_mc_i - * @irq_num: A user defined number associated with this IRQ - */ - struct dprc_irq_cfg { +- * destroyed +- */ +-#define DPRC_IRQ_EVENT_OBJ_DESTROYED 0x00000020 +- +-/* Irq event - Indicates that object is created at the container */ +-#define DPRC_IRQ_EVENT_OBJ_CREATED 0x00000040 +- +-/** +- * struct dprc_irq_cfg - IRQ configuration +- * @paddr: Address that must be written to signal a message-based interrupt +- * @val: Value to write into irq_addr address +- * @irq_num: A user defined number associated with this IRQ +- */ +-struct dprc_irq_cfg { - phys_addr_t paddr; - u32 val; - int irq_num; @@ -10744,73 +18131,20 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - u16 token, - u8 irq_index, - u32 status); -+ phys_addr_t paddr; -+ u32 val; -+ int irq_num; -+}; -+ -+int dprc_set_irq(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u8 irq_index, -+ struct dprc_irq_cfg *irq_cfg); -+ -+int dprc_get_irq(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u8 irq_index, -+ int *type, -+ struct dprc_irq_cfg *irq_cfg); -+ -+int dprc_set_irq_enable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u8 irq_index, -+ u8 en); -+ -+int dprc_get_irq_enable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u8 irq_index, -+ u8 *en); -+ -+int dprc_set_irq_mask(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u8 irq_index, -+ u32 mask); -+ -+int dprc_get_irq_mask(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u8 irq_index, -+ u32 *mask); -+ -+int dprc_get_irq_status(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u8 irq_index, -+ u32 *status); -+ -+int dprc_clear_irq_status(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u8 irq_index, -+ u32 status); - - /** - * struct dprc_attributes - Container attributes -@@ -231,114 +152,23 @@ int dprc_clear_irq_status(struct fsl_mc_ - * @icid: Container's ICID - * @portal_id: Container's portal ID - * @options: Container's options as set at container's creation +- +-/** +- * struct dprc_attributes - Container attributes +- * @container_id: Container's ID +- * @icid: Container's ICID +- * @portal_id: Container's portal ID +- * @options: Container's options as set at container's creation - * @version: DPRC version - */ - struct dprc_attributes { - int container_id; - u16 icid; - int portal_id; - u64 options; +- */ +-struct dprc_attributes { +- int container_id; +- u16 icid; +- int portal_id; +- u64 options; - /** - * struct version - DPRC version - * @major: DPRC major version @@ -10820,8 +18154,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - u16 major; - u16 minor; - } version; - }; - +-}; +- -int dprc_get_attributes(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, @@ -10907,34 +18241,53 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - u16 token, - int pool_index, - char *type); -+int dprc_get_attributes(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ struct dprc_attributes *attributes); - - int dprc_get_obj_count(struct fsl_mc_io *mc_io, +- +-int dprc_get_obj_count(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - int *obj_count); -+ u32 cmd_flags, -+ u16 token, -+ int *obj_count); - - /* Objects Attributes Flags */ - -@@ -353,7 +183,7 @@ int dprc_get_obj_count(struct fsl_mc_io - * masters; - * user is responsible for proper memory handling through IOMMU configuration. - */ +- +-/* Objects Attributes Flags */ +- +-/* Opened state - Indicates that an object is open by at least one owner */ +-#define DPRC_OBJ_STATE_OPEN 0x00000001 +-/* Plugged state - Indicates that the object is plugged */ +-#define DPRC_OBJ_STATE_PLUGGED 0x00000002 +- +-/** +- * Shareability flag - Object flag indicating no memory shareability. +- * the object generates memory accesses that are non coherent with other +- * masters; +- * user is responsible for proper memory handling through IOMMU configuration. +- */ -#define DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY 0x0001 -+#define DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY 0x0001 - - /** - * struct dprc_obj_desc - Object descriptor, returned from dprc_get_obj() -@@ -381,41 +211,41 @@ struct dprc_obj_desc { - u16 flags; - }; - +- +-/** +- * struct dprc_obj_desc - Object descriptor, returned from dprc_get_obj() +- * @type: Type of object: NULL terminated string +- * @id: ID of logical object resource +- * @vendor: Object vendor identifier +- * @ver_major: Major version number +- * @ver_minor: Minor version number +- * @irq_count: Number of interrupts supported by the object +- * @region_count: Number of mappable regions supported by the object +- * @state: Object state: combination of DPRC_OBJ_STATE_ states +- * @label: Object label +- * @flags: Object's flags +- */ +-struct dprc_obj_desc { +- char type[16]; +- int id; +- u16 vendor; +- u16 ver_major; +- u16 ver_minor; +- u8 irq_count; +- u8 region_count; +- u32 state; +- char label[16]; +- u16 flags; +-}; +- -int dprc_get_obj(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, @@ -10970,48 +18323,19 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - u16 token, - char *type, - int *res_count); -+int dprc_get_obj(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ int obj_index, -+ struct dprc_obj_desc *obj_desc); -+ -+int dprc_get_obj_desc(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ char *obj_type, -+ int obj_id, -+ struct dprc_obj_desc *obj_desc); -+ -+int dprc_set_obj_irq(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ char *obj_type, -+ int obj_id, -+ u8 irq_index, -+ struct dprc_irq_cfg *irq_cfg); -+ -+int dprc_get_obj_irq(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ char *obj_type, -+ int obj_id, -+ u8 irq_index, -+ int *type, -+ struct dprc_irq_cfg *irq_cfg); -+ -+int dprc_get_res_count(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ char *type, -+ int *res_count); - - /** - * enum dprc_iter_status - Iteration status -@@ -429,27 +259,6 @@ enum dprc_iter_status { - DPRC_ITER_STATUS_LAST = 2 - }; - +- +-/** +- * enum dprc_iter_status - Iteration status +- * @DPRC_ITER_STATUS_FIRST: Perform first iteration +- * @DPRC_ITER_STATUS_MORE: Indicates more/next iteration is needed +- * @DPRC_ITER_STATUS_LAST: Indicates last iteration +- */ +-enum dprc_iter_status { +- DPRC_ITER_STATUS_FIRST = 0, +- DPRC_ITER_STATUS_MORE = 1, +- DPRC_ITER_STATUS_LAST = 2 +-}; +- -/** - * struct dprc_res_ids_range_desc - Resource ID range descriptor - * @base_id: Base resource ID of this range @@ -11033,13 +18357,37 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - char *type, - struct dprc_res_ids_range_desc *range_desc); - - /* Region flags */ - /* Cacheable - Indicates that region should be mapped as cacheable */ - #define DPRC_REGION_CACHEABLE 0x00000001 -@@ -481,64 +290,27 @@ struct dprc_region_desc { - enum dprc_region_type type; - }; - +-/* Region flags */ +-/* Cacheable - Indicates that region should be mapped as cacheable */ +-#define DPRC_REGION_CACHEABLE 0x00000001 +- +-/** +- * enum dprc_region_type - Region type +- * @DPRC_REGION_TYPE_MC_PORTAL: MC portal region +- * @DPRC_REGION_TYPE_QBMAN_PORTAL: Qbman portal region +- */ +-enum dprc_region_type { +- DPRC_REGION_TYPE_MC_PORTAL, +- DPRC_REGION_TYPE_QBMAN_PORTAL +-}; +- +-/** +- * struct dprc_region_desc - Mappable region descriptor +- * @base_offset: Region offset from region's base address. +- * For DPMCP and DPRC objects, region base is offset from SoC MC portals +- * base address; For DPIO, region base is offset from SoC QMan portals +- * base address +- * @size: Region size (in bytes) +- * @flags: Region attributes +- * @type: Portal region type +- */ +-struct dprc_region_desc { +- u32 base_offset; +- u32 size; +- u32 flags; +- enum dprc_region_type type; +-}; +- -int dprc_get_obj_region(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, @@ -11054,14 +18402,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - char *obj_type, - int obj_id, - char *label); -+int dprc_get_obj_region(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ char *obj_type, -+ int obj_id, -+ u8 region_index, -+ struct dprc_region_desc *region_desc); - +- -/** - * struct dprc_endpoint - Endpoint description for link connect/disconnect - * operations @@ -11075,11 +18416,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - int id; - int if_id; -}; -+int dprc_get_api_version(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 *major_ver, -+ u16 *minor_ver); - +- -/** - * struct dprc_connection_cfg - Connection configuration. - * Used for virtual connections only @@ -11090,10 +18427,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - u32 committed_rate; - u32 max_rate; -}; -+int dprc_get_container_id(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ int *container_id); - +- -int dprc_connect(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, @@ -11112,102 +18446,818 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - const struct dprc_endpoint *endpoint1, - struct dprc_endpoint *endpoint2, - int *state); -+int dprc_reset_container(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ int child_container_id); - - #endif /* _FSL_DPRC_H */ - +- +-#endif /* _FSL_DPRC_H */ +- --- a/drivers/staging/fsl-mc/include/mc-bus.h -+++ b/drivers/staging/fsl-mc/include/mc-bus.h -@@ -1,7 +1,7 @@ - /* - * Freescale Management Complex (MC) bus declarations - * ++++ /dev/null +@@ -1,111 +0,0 @@ +-/* +- * Freescale Management Complex (MC) bus declarations +- * - * Copyright (C) 2014 Freescale Semiconductor, Inc. -+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. - * Author: German Rivera <German.Rivera@freescale.com> - * - * This file is licensed under the terms of the GNU General Public -@@ -42,8 +42,8 @@ struct msi_domain_info; - */ - struct fsl_mc_resource_pool { - enum fsl_mc_pool_type type; +- * Author: German Rivera <German.Rivera@freescale.com> +- * +- * 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_MC_MCBUS_H_ +-#define _FSL_MC_MCBUS_H_ +- +-#include "../include/mc.h" +-#include <linux/mutex.h> +- +-struct irq_domain; +-struct msi_domain_info; +- +-/** +- * Maximum number of total IRQs that can be pre-allocated for an MC bus' +- * IRQ pool +- */ +-#define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256 +- +-#ifdef CONFIG_FSL_MC_BUS +-#define dev_is_fsl_mc(_dev) ((_dev)->bus == &fsl_mc_bus_type) +-#else +-/* If fsl-mc bus is not present device cannot belong to fsl-mc bus */ +-#define dev_is_fsl_mc(_dev) (0) +-#endif +- +-/** +- * struct fsl_mc_resource_pool - Pool of MC resources of a given +- * type +- * @type: type of resources in the pool +- * @max_count: maximum number of resources in the pool +- * @free_count: number of free resources in the pool +- * @mutex: mutex to serialize access to the pool's free list +- * @free_list: anchor node of list of free resources in the pool +- * @mc_bus: pointer to the MC bus that owns this resource pool +- */ +-struct fsl_mc_resource_pool { +- enum fsl_mc_pool_type type; - int16_t max_count; - int16_t free_count; -+ int max_count; -+ int free_count; - struct mutex mutex; /* serializes access to free_list */ - struct list_head free_list; - struct fsl_mc_bus *mc_bus; -@@ -73,6 +73,7 @@ struct fsl_mc_bus { - int dprc_scan_container(struct fsl_mc_device *mc_bus_dev); - - int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, -+ const char *driver_override, - unsigned int *total_irq_count); - - int __init dprc_driver_init(void); +- struct mutex mutex; /* serializes access to free_list */ +- struct list_head free_list; +- struct fsl_mc_bus *mc_bus; +-}; +- +-/** +- * struct fsl_mc_bus - logical bus that corresponds to a physical DPRC +- * @mc_dev: fsl-mc device for the bus device itself. +- * @resource_pools: array of resource pools (one pool per resource type) +- * for this MC bus. These resources represent allocatable entities +- * from the physical DPRC. +- * @irq_resources: Pointer to array of IRQ objects for the IRQ pool +- * @scan_mutex: Serializes bus scanning +- * @dprc_attr: DPRC attributes +- */ +-struct fsl_mc_bus { +- struct fsl_mc_device mc_dev; +- struct fsl_mc_resource_pool resource_pools[FSL_MC_NUM_POOL_TYPES]; +- struct fsl_mc_device_irq *irq_resources; +- struct mutex scan_mutex; /* serializes bus scanning */ +- struct dprc_attributes dprc_attr; +-}; +- +-#define to_fsl_mc_bus(_mc_dev) \ +- container_of(_mc_dev, struct fsl_mc_bus, mc_dev) +- +-int dprc_scan_container(struct fsl_mc_device *mc_bus_dev); +- +-int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, +- unsigned int *total_irq_count); +- +-int __init dprc_driver_init(void); +- +-void dprc_driver_exit(void); +- +-int __init fsl_mc_allocator_driver_init(void); +- +-void fsl_mc_allocator_driver_exit(void); +- +-struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, +- struct msi_domain_info *info, +- struct irq_domain *parent); +- +-int fsl_mc_find_msi_domain(struct device *mc_platform_dev, +- struct irq_domain **mc_msi_domain); +- +-int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, +- unsigned int irq_count); +- +-void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus); +- +-void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev); +- +-void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev); +- +-bool fsl_mc_bus_exists(void); +- +-void fsl_mc_get_root_dprc(struct device *dev, +- struct device **root_dprc_dev); +- +-bool fsl_mc_is_root_dprc(struct device *dev); +- +-extern struct bus_type fsl_mc_bus_type; +- +-#endif /* _FSL_MC_MCBUS_H_ */ --- a/drivers/staging/fsl-mc/include/mc-cmd.h -+++ b/drivers/staging/fsl-mc/include/mc-cmd.h -@@ -1,4 +1,5 @@ ++++ /dev/null +@@ -1,108 +0,0 @@ -/* Copyright 2013-2015 Freescale Semiconductor Inc. -+/* -+ * Copyright 2013-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: -@@ -48,6 +49,15 @@ struct mc_command { - u64 params[MC_CMD_NUM_OF_PARAMS]; - }; - -+struct mc_rsp_create { -+ __le32 object_id; -+}; -+ -+struct mc_rsp_api_ver { -+ __le16 major_ver; -+ __le16 minor_ver; -+}; -+ - enum mc_cmd_status { - MC_CMD_STATUS_OK = 0x0, /* Completed successfully */ - MC_CMD_STATUS_READY = 0x1, /* Ready to be processed */ -@@ -72,11 +82,6 @@ enum mc_cmd_status { - /* Command completion flag */ - #define MC_CMD_FLAG_INTR_DIS 0x01 - +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of the above-listed copyright holders nor the +- * names of any contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +- * POSSIBILITY OF SUCH DAMAGE. +- */ +-#ifndef __FSL_MC_CMD_H +-#define __FSL_MC_CMD_H +- +-#define MC_CMD_NUM_OF_PARAMS 7 +- +-struct mc_cmd_header { +- u8 src_id; +- u8 flags_hw; +- u8 status; +- u8 flags_sw; +- __le16 token; +- __le16 cmd_id; +-}; +- +-struct mc_command { +- u64 header; +- u64 params[MC_CMD_NUM_OF_PARAMS]; +-}; +- +-enum mc_cmd_status { +- MC_CMD_STATUS_OK = 0x0, /* Completed successfully */ +- MC_CMD_STATUS_READY = 0x1, /* Ready to be processed */ +- MC_CMD_STATUS_AUTH_ERR = 0x3, /* Authentication error */ +- MC_CMD_STATUS_NO_PRIVILEGE = 0x4, /* No privilege */ +- MC_CMD_STATUS_DMA_ERR = 0x5, /* DMA or I/O error */ +- MC_CMD_STATUS_CONFIG_ERR = 0x6, /* Configuration error */ +- MC_CMD_STATUS_TIMEOUT = 0x7, /* Operation timed out */ +- MC_CMD_STATUS_NO_RESOURCE = 0x8, /* No resources */ +- MC_CMD_STATUS_NO_MEMORY = 0x9, /* No memory available */ +- MC_CMD_STATUS_BUSY = 0xA, /* Device is busy */ +- MC_CMD_STATUS_UNSUPPORTED_OP = 0xB, /* Unsupported operation */ +- MC_CMD_STATUS_INVALID_STATE = 0xC /* Invalid state */ +-}; +- +-/* +- * MC command flags +- */ +- +-/* High priority flag */ +-#define MC_CMD_FLAG_PRI 0x80 +-/* Command completion flag */ +-#define MC_CMD_FLAG_INTR_DIS 0x01 +- -#define MC_CMD_HDR_CMDID_MASK 0xFFF0 -#define MC_CMD_HDR_CMDID_SHIFT 4 -#define MC_CMD_HDR_TOKEN_MASK 0xFFC0 -#define MC_CMD_HDR_TOKEN_SHIFT 6 - - static inline u64 mc_encode_cmd_header(u16 cmd_id, - u32 cmd_flags, - u16 token) -@@ -84,10 +89,8 @@ static inline u64 mc_encode_cmd_header(u - u64 header = 0; - struct mc_cmd_header *hdr = (struct mc_cmd_header *)&header; - +-static inline u64 mc_encode_cmd_header(u16 cmd_id, +- u32 cmd_flags, +- u16 token) +-{ +- u64 header = 0; +- struct mc_cmd_header *hdr = (struct mc_cmd_header *)&header; +- - hdr->cmd_id = cpu_to_le16((cmd_id << MC_CMD_HDR_CMDID_SHIFT) & - MC_CMD_HDR_CMDID_MASK); - hdr->token = cpu_to_le16((token << MC_CMD_HDR_TOKEN_SHIFT) & - MC_CMD_HDR_TOKEN_MASK); +- hdr->status = MC_CMD_STATUS_READY; +- if (cmd_flags & MC_CMD_FLAG_PRI) +- hdr->flags_hw = MC_CMD_FLAG_PRI; +- if (cmd_flags & MC_CMD_FLAG_INTR_DIS) +- hdr->flags_sw = MC_CMD_FLAG_INTR_DIS; +- +- return header; +-} +- +-static inline u16 mc_cmd_hdr_read_token(struct mc_command *cmd) +-{ +- struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header; +- u16 token = le16_to_cpu(hdr->token); +- +- return (token & MC_CMD_HDR_TOKEN_MASK) >> MC_CMD_HDR_TOKEN_SHIFT; +-} +- +-#endif /* __FSL_MC_CMD_H */ +--- a/drivers/staging/fsl-mc/include/mc-sys.h ++++ /dev/null +@@ -1,98 +0,0 @@ +-/* Copyright 2013-2014 Freescale Semiconductor Inc. +- * +- * Interface of the I/O services to send MC commands to the MC hardware +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of the above-listed copyright holders nor the +- * names of any contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +- * POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#ifndef _FSL_MC_SYS_H +-#define _FSL_MC_SYS_H +- +-#include <linux/types.h> +-#include <linux/errno.h> +-#include <linux/mutex.h> +-#include <linux/spinlock.h> +- +-/** +- * Bit masks for a MC I/O object (struct fsl_mc_io) flags +- */ +-#define FSL_MC_IO_ATOMIC_CONTEXT_PORTAL 0x0001 +- +-struct fsl_mc_resource; +-struct mc_command; +- +-/** +- * struct fsl_mc_io - MC I/O object to be passed-in to mc_send_command() +- * @dev: device associated with this Mc I/O object +- * @flags: flags for mc_send_command() +- * @portal_size: MC command portal size in bytes +- * @portal_phys_addr: MC command portal physical address +- * @portal_virt_addr: MC command portal virtual address +- * @dpmcp_dev: pointer to the DPMCP device associated with the MC portal. +- * +- * Fields are only meaningful if the FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is not +- * set: +- * @mutex: Mutex to serialize mc_send_command() calls that use the same MC +- * portal, if the fsl_mc_io object was created with the +- * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag off. mc_send_command() calls for this +- * fsl_mc_io object must be made only from non-atomic context. +- * +- * Fields are only meaningful if the FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is +- * set: +- * @spinlock: Spinlock to serialize mc_send_command() calls that use the same MC +- * portal, if the fsl_mc_io object was created with the +- * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag on. mc_send_command() calls for this +- * fsl_mc_io object can be made from atomic or non-atomic context. +- */ +-struct fsl_mc_io { +- struct device *dev; +- u16 flags; +- u16 portal_size; +- phys_addr_t portal_phys_addr; +- void __iomem *portal_virt_addr; +- struct fsl_mc_device *dpmcp_dev; +- union { +- /* +- * This field is only meaningful if the +- * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is not set +- */ +- struct mutex mutex; /* serializes mc_send_command() */ +- +- /* +- * This field is only meaningful if the +- * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is set +- */ +- spinlock_t spinlock; /* serializes mc_send_command() */ +- }; +-}; +- +-int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd); +- +-#endif /* _FSL_MC_SYS_H */ +--- a/drivers/staging/fsl-mc/include/mc.h ++++ /dev/null +@@ -1,201 +0,0 @@ +-/* +- * Freescale Management Complex (MC) bus public interface +- * +- * Copyright (C) 2014 Freescale Semiconductor, Inc. +- * Author: German Rivera <German.Rivera@freescale.com> +- * +- * 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_MC_H_ +-#define _FSL_MC_H_ +- +-#include <linux/device.h> +-#include <linux/mod_devicetable.h> +-#include <linux/interrupt.h> +-#include "../include/dprc.h" +- +-#define FSL_MC_VENDOR_FREESCALE 0x1957 +- +-struct fsl_mc_device; +-struct fsl_mc_io; +- +-/** +- * struct fsl_mc_driver - MC object device driver object +- * @driver: Generic device driver +- * @match_id_table: table of supported device matching Ids +- * @probe: Function called when a device is added +- * @remove: Function called when a device is removed +- * @shutdown: Function called at shutdown time to quiesce the device +- * @suspend: Function called when a device is stopped +- * @resume: Function called when a device is resumed +- * +- * Generic DPAA device driver object for device drivers that are registered +- * with a DPRC bus. This structure is to be embedded in each device-specific +- * driver structure. +- */ +-struct fsl_mc_driver { +- struct device_driver driver; +- const struct fsl_mc_device_id *match_id_table; +- int (*probe)(struct fsl_mc_device *dev); +- int (*remove)(struct fsl_mc_device *dev); +- void (*shutdown)(struct fsl_mc_device *dev); +- int (*suspend)(struct fsl_mc_device *dev, pm_message_t state); +- int (*resume)(struct fsl_mc_device *dev); +-}; +- +-#define to_fsl_mc_driver(_drv) \ +- container_of(_drv, struct fsl_mc_driver, driver) +- +-/** +- * enum fsl_mc_pool_type - Types of allocatable MC bus resources +- * +- * Entries in these enum are used as indices in the array of resource +- * pools of an fsl_mc_bus object. +- */ +-enum fsl_mc_pool_type { +- FSL_MC_POOL_DPMCP = 0x0, /* corresponds to "dpmcp" in the MC */ +- FSL_MC_POOL_DPBP, /* corresponds to "dpbp" in the MC */ +- FSL_MC_POOL_DPCON, /* corresponds to "dpcon" in the MC */ +- FSL_MC_POOL_IRQ, +- +- /* +- * NOTE: New resource pool types must be added before this entry +- */ +- FSL_MC_NUM_POOL_TYPES +-}; +- +-/** +- * struct fsl_mc_resource - MC generic resource +- * @type: type of resource +- * @id: unique MC resource Id within the resources of the same type +- * @data: pointer to resource-specific data if the resource is currently +- * allocated, or NULL if the resource is not currently allocated. +- * @parent_pool: pointer to the parent resource pool from which this +- * resource is allocated from. +- * @node: Node in the free list of the corresponding resource pool +- * +- * NOTE: This structure is to be embedded as a field of specific +- * MC resource structures. +- */ +-struct fsl_mc_resource { +- enum fsl_mc_pool_type type; +- int32_t id; +- void *data; +- struct fsl_mc_resource_pool *parent_pool; +- struct list_head node; +-}; +- +-/** +- * struct fsl_mc_device_irq - MC object device message-based interrupt +- * @msi_desc: pointer to MSI descriptor allocated by fsl_mc_msi_alloc_descs() +- * @mc_dev: MC object device that owns this interrupt +- * @dev_irq_index: device-relative IRQ index +- * @resource: MC generic resource associated with the interrupt +- */ +-struct fsl_mc_device_irq { +- struct msi_desc *msi_desc; +- struct fsl_mc_device *mc_dev; +- u8 dev_irq_index; +- struct fsl_mc_resource resource; +-}; +- +-#define to_fsl_mc_irq(_mc_resource) \ +- container_of(_mc_resource, struct fsl_mc_device_irq, resource) +- +-/** +- * Bit masks for a MC object device (struct fsl_mc_device) flags +- */ +-#define FSL_MC_IS_DPRC 0x0001 +- +-/** +- * struct fsl_mc_device - MC object device object +- * @dev: Linux driver model device object +- * @dma_mask: Default DMA mask +- * @flags: MC object device flags +- * @icid: Isolation context ID for the device +- * @mc_handle: MC handle for the corresponding MC object opened +- * @mc_io: Pointer to MC IO object assigned to this device or +- * NULL if none. +- * @obj_desc: MC description of the DPAA device +- * @regions: pointer to array of MMIO region entries +- * @irqs: pointer to array of pointers to interrupts allocated to this device +- * @resource: generic resource associated with this MC object device, if any. +- * +- * Generic device object for MC object devices that are "attached" to a +- * MC bus. +- * +- * NOTES: +- * - For a non-DPRC object its icid is the same as its parent DPRC's icid. +- * - The SMMU notifier callback gets invoked after device_add() has been +- * called for an MC object device, but before the device-specific probe +- * callback gets called. +- * - DP_OBJ_DPRC objects are the only MC objects that have built-in MC +- * portals. For all other MC objects, their device drivers are responsible for +- * allocating MC portals for them by calling fsl_mc_portal_allocate(). +- * - Some types of MC objects (e.g., DP_OBJ_DPBP, DP_OBJ_DPCON) are +- * treated as resources that can be allocated/deallocated from the +- * corresponding resource pool in the object's parent DPRC, using the +- * fsl_mc_object_allocate()/fsl_mc_object_free() functions. These MC objects +- * are known as "allocatable" objects. For them, the corresponding +- * fsl_mc_device's 'resource' points to the associated resource object. +- * For MC objects that are not allocatable (e.g., DP_OBJ_DPRC, DP_OBJ_DPNI), +- * 'resource' is NULL. +- */ +-struct fsl_mc_device { +- struct device dev; +- u64 dma_mask; +- u16 flags; +- u16 icid; +- u16 mc_handle; +- struct fsl_mc_io *mc_io; +- struct dprc_obj_desc obj_desc; +- struct resource *regions; +- struct fsl_mc_device_irq **irqs; +- struct fsl_mc_resource *resource; +-}; +- +-#define to_fsl_mc_device(_dev) \ +- container_of(_dev, struct fsl_mc_device, dev) +- +-/* +- * module_fsl_mc_driver() - Helper macro for drivers that don't do +- * anything special in module init/exit. This eliminates a lot of +- * boilerplate. Each module may only use this macro once, and +- * calling it replaces module_init() and module_exit() +- */ +-#define module_fsl_mc_driver(__fsl_mc_driver) \ +- module_driver(__fsl_mc_driver, fsl_mc_driver_register, \ +- fsl_mc_driver_unregister) +- +-/* +- * Macro to avoid include chaining to get THIS_MODULE +- */ +-#define fsl_mc_driver_register(drv) \ +- __fsl_mc_driver_register(drv, THIS_MODULE) +- +-int __must_check __fsl_mc_driver_register(struct fsl_mc_driver *fsl_mc_driver, +- struct module *owner); +- +-void fsl_mc_driver_unregister(struct fsl_mc_driver *driver); +- +-int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, +- u16 mc_io_flags, +- struct fsl_mc_io **new_mc_io); +- +-void fsl_mc_portal_free(struct fsl_mc_io *mc_io); +- +-int fsl_mc_portal_reset(struct fsl_mc_io *mc_io); +- +-int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev, +- enum fsl_mc_pool_type pool_type, +- struct fsl_mc_device **new_mc_adev); +- +-void fsl_mc_object_free(struct fsl_mc_device *mc_adev); +- +-int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev); +- +-void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev); +- +-#endif /* _FSL_MC_H_ */ +--- /dev/null ++++ b/include/linux/fsl/mc.h +@@ -0,0 +1,1025 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Freescale Management Complex (MC) bus public interface ++ * ++ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. ++ * Author: German Rivera <German.Rivera@freescale.com> ++ * ++ */ ++#ifndef _FSL_MC_H_ ++#define _FSL_MC_H_ ++ ++#include <linux/device.h> ++#include <linux/mod_devicetable.h> ++#include <linux/interrupt.h> ++#include <linux/cdev.h> ++#include <uapi/linux/fsl_mc.h> ++ ++#define FSL_MC_VENDOR_FREESCALE 0x1957 ++ ++struct irq_domain; ++struct msi_domain_info; ++ ++struct fsl_mc_device; ++struct fsl_mc_io; ++ ++/** ++ * struct fsl_mc_driver - MC object device driver object ++ * @driver: Generic device driver ++ * @match_id_table: table of supported device matching Ids ++ * @probe: Function called when a device is added ++ * @remove: Function called when a device is removed ++ * @shutdown: Function called at shutdown time to quiesce the device ++ * @suspend: Function called when a device is stopped ++ * @resume: Function called when a device is resumed ++ * ++ * Generic DPAA device driver object for device drivers that are registered ++ * with a DPRC bus. This structure is to be embedded in each device-specific ++ * driver structure. ++ */ ++struct fsl_mc_driver { ++ struct device_driver driver; ++ const struct fsl_mc_device_id *match_id_table; ++ int (*probe)(struct fsl_mc_device *dev); ++ int (*remove)(struct fsl_mc_device *dev); ++ void (*shutdown)(struct fsl_mc_device *dev); ++ int (*suspend)(struct fsl_mc_device *dev, pm_message_t state); ++ int (*resume)(struct fsl_mc_device *dev); ++}; ++ ++#define to_fsl_mc_driver(_drv) \ ++ container_of(_drv, struct fsl_mc_driver, driver) ++ ++#define to_fsl_mc_bus(_mc_dev) \ ++ container_of(_mc_dev, struct fsl_mc_bus, mc_dev) ++ ++/** ++ * enum fsl_mc_pool_type - Types of allocatable MC bus resources ++ * ++ * Entries in these enum are used as indices in the array of resource ++ * pools of an fsl_mc_bus object. ++ */ ++enum fsl_mc_pool_type { ++ FSL_MC_POOL_DPMCP = 0x0, /* corresponds to "dpmcp" in the MC */ ++ FSL_MC_POOL_DPBP, /* corresponds to "dpbp" in the MC */ ++ FSL_MC_POOL_DPCON, /* corresponds to "dpcon" in the MC */ ++ FSL_MC_POOL_IRQ, ++ ++ /* ++ * NOTE: New resource pool types must be added before this entry ++ */ ++ FSL_MC_NUM_POOL_TYPES ++}; ++ ++/** ++ * struct fsl_mc_resource - MC generic resource ++ * @type: type of resource ++ * @id: unique MC resource Id within the resources of the same type ++ * @data: pointer to resource-specific data if the resource is currently ++ * allocated, or NULL if the resource is not currently allocated. ++ * @parent_pool: pointer to the parent resource pool from which this ++ * resource is allocated from. ++ * @node: Node in the free list of the corresponding resource pool ++ * ++ * NOTE: This structure is to be embedded as a field of specific ++ * MC resource structures. ++ */ ++struct fsl_mc_resource { ++ enum fsl_mc_pool_type type; ++ s32 id; ++ void *data; ++ struct fsl_mc_resource_pool *parent_pool; ++ struct list_head node; ++}; ++ ++/** ++ * struct fsl_mc_device_irq - MC object device message-based interrupt ++ * @msi_desc: pointer to MSI descriptor allocated by fsl_mc_msi_alloc_descs() ++ * @mc_dev: MC object device that owns this interrupt ++ * @dev_irq_index: device-relative IRQ index ++ * @resource: MC generic resource associated with the interrupt ++ */ ++struct fsl_mc_device_irq { ++ struct msi_desc *msi_desc; ++ struct fsl_mc_device *mc_dev; ++ u8 dev_irq_index; ++ struct fsl_mc_resource resource; ++}; ++ ++#define to_fsl_mc_irq(_mc_resource) \ ++ container_of(_mc_resource, struct fsl_mc_device_irq, resource) ++ ++/* Opened state - Indicates that an object is open by at least one owner */ ++#define FSL_MC_OBJ_STATE_OPEN 0x00000001 ++/* Plugged state - Indicates that the object is plugged */ ++#define FSL_MC_OBJ_STATE_PLUGGED 0x00000002 ++ ++/** ++ * Shareability flag - Object flag indicating no memory shareability. ++ * the object generates memory accesses that are non coherent with other ++ * masters; ++ * user is responsible for proper memory handling through IOMMU configuration. ++ */ ++#define FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY 0x0001 ++ ++/** ++ * struct fsl_mc_obj_desc - Object descriptor ++ * @type: Type of object: NULL terminated string ++ * @id: ID of logical object resource ++ * @vendor: Object vendor identifier ++ * @ver_major: Major version number ++ * @ver_minor: Minor version number ++ * @irq_count: Number of interrupts supported by the object ++ * @region_count: Number of mappable regions supported by the object ++ * @state: Object state: combination of FSL_MC_OBJ_STATE_ states ++ * @label: Object label: NULL terminated string ++ * @flags: Object's flags ++ */ ++struct fsl_mc_obj_desc { ++ char type[16]; ++ int id; ++ u16 vendor; ++ u16 ver_major; ++ u16 ver_minor; ++ u8 irq_count; ++ u8 region_count; ++ u32 state; ++ char label[16]; ++ u16 flags; ++}; ++ ++/** ++ * Bit masks for a MC object device (struct fsl_mc_device) flags ++ */ ++#define FSL_MC_IS_DPRC 0x0001 ++ ++/** ++ * struct fsl_mc_device - MC object device object ++ * @dev: Linux driver model device object ++ * @dma_mask: Default DMA mask ++ * @flags: MC object device flags ++ * @icid: Isolation context ID for the device ++ * @mc_handle: MC handle for the corresponding MC object opened ++ * @mc_io: Pointer to MC IO object assigned to this device or ++ * NULL if none. ++ * @obj_desc: MC description of the DPAA device ++ * @regions: pointer to array of MMIO region entries ++ * @irqs: pointer to array of pointers to interrupts allocated to this device ++ * @resource: generic resource associated with this MC object device, if any. ++ * @driver_override: Driver name to force a match ++ * ++ * Generic device object for MC object devices that are "attached" to a ++ * MC bus. ++ * ++ * NOTES: ++ * - For a non-DPRC object its icid is the same as its parent DPRC's icid. ++ * - The SMMU notifier callback gets invoked after device_add() has been ++ * called for an MC object device, but before the device-specific probe ++ * callback gets called. ++ * - DP_OBJ_DPRC objects are the only MC objects that have built-in MC ++ * portals. For all other MC objects, their device drivers are responsible for ++ * allocating MC portals for them by calling fsl_mc_portal_allocate(). ++ * - Some types of MC objects (e.g., DP_OBJ_DPBP, DP_OBJ_DPCON) are ++ * treated as resources that can be allocated/deallocated from the ++ * corresponding resource pool in the object's parent DPRC, using the ++ * fsl_mc_object_allocate()/fsl_mc_object_free() functions. These MC objects ++ * are known as "allocatable" objects. For them, the corresponding ++ * fsl_mc_device's 'resource' points to the associated resource object. ++ * For MC objects that are not allocatable (e.g., DP_OBJ_DPRC, DP_OBJ_DPNI), ++ * 'resource' is NULL. ++ */ ++struct fsl_mc_device { ++ struct device dev; ++ u64 dma_mask; ++ u16 flags; ++ u32 icid; ++ u16 mc_handle; ++ struct fsl_mc_io *mc_io; ++ struct fsl_mc_obj_desc obj_desc; ++ struct resource *regions; ++ struct fsl_mc_device_irq **irqs; ++ struct fsl_mc_resource *resource; ++ const char *driver_override; ++}; ++ ++#define to_fsl_mc_device(_dev) \ ++ container_of(_dev, struct fsl_mc_device, dev) ++ ++struct mc_cmd_header { ++ u8 src_id; ++ u8 flags_hw; ++ u8 status; ++ u8 flags_sw; ++ __le16 token; ++ __le16 cmd_id; ++}; ++ ++enum mc_cmd_status { ++ MC_CMD_STATUS_OK = 0x0, /* Completed successfully */ ++ MC_CMD_STATUS_READY = 0x1, /* Ready to be processed */ ++ MC_CMD_STATUS_AUTH_ERR = 0x3, /* Authentication error */ ++ MC_CMD_STATUS_NO_PRIVILEGE = 0x4, /* No privilege */ ++ MC_CMD_STATUS_DMA_ERR = 0x5, /* DMA or I/O error */ ++ MC_CMD_STATUS_CONFIG_ERR = 0x6, /* Configuration error */ ++ MC_CMD_STATUS_TIMEOUT = 0x7, /* Operation timed out */ ++ MC_CMD_STATUS_NO_RESOURCE = 0x8, /* No resources */ ++ MC_CMD_STATUS_NO_MEMORY = 0x9, /* No memory available */ ++ MC_CMD_STATUS_BUSY = 0xA, /* Device is busy */ ++ MC_CMD_STATUS_UNSUPPORTED_OP = 0xB, /* Unsupported operation */ ++ MC_CMD_STATUS_INVALID_STATE = 0xC /* Invalid state */ ++}; ++ ++/* ++ * MC command flags ++ */ ++ ++/* High priority flag */ ++#define MC_CMD_FLAG_PRI 0x80 ++/* Command completion flag */ ++#define MC_CMD_FLAG_INTR_DIS 0x01 ++ ++static inline u64 mc_encode_cmd_header(u16 cmd_id, ++ u32 cmd_flags, ++ u16 token) ++{ ++ u64 header = 0; ++ struct mc_cmd_header *hdr = (struct mc_cmd_header *)&header; ++ + hdr->cmd_id = cpu_to_le16(cmd_id); + hdr->token = cpu_to_le16(token); - hdr->status = MC_CMD_STATUS_READY; - if (cmd_flags & MC_CMD_FLAG_PRI) - hdr->flags_hw = MC_CMD_FLAG_PRI; -@@ -102,7 +105,26 @@ static inline u16 mc_cmd_hdr_read_token( - struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header; - u16 token = le16_to_cpu(hdr->token); - -- return (token & MC_CMD_HDR_TOKEN_MASK) >> MC_CMD_HDR_TOKEN_SHIFT; ++ hdr->status = MC_CMD_STATUS_READY; ++ if (cmd_flags & MC_CMD_FLAG_PRI) ++ hdr->flags_hw = MC_CMD_FLAG_PRI; ++ if (cmd_flags & MC_CMD_FLAG_INTR_DIS) ++ hdr->flags_sw = MC_CMD_FLAG_INTR_DIS; ++ ++ return header; ++} ++ ++static inline u16 mc_cmd_hdr_read_token(struct fsl_mc_command *cmd) ++{ ++ struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header; ++ u16 token = le16_to_cpu(hdr->token); ++ + return token; +} + -+static inline u32 mc_cmd_read_object_id(struct mc_command *cmd) ++struct mc_rsp_create { ++ __le32 object_id; ++}; ++ ++struct mc_rsp_api_ver { ++ __le16 major_ver; ++ __le16 minor_ver; ++}; ++ ++static inline u32 mc_cmd_read_object_id(struct fsl_mc_command *cmd) +{ + struct mc_rsp_create *rsp_params; + @@ -11215,7 +19265,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return le32_to_cpu(rsp_params->object_id); +} + -+static inline void mc_cmd_read_api_version(struct mc_command *cmd, ++static inline void mc_cmd_read_api_version(struct fsl_mc_command *cmd, + u16 *major_ver, + u16 *minor_ver) +{ @@ -11224,74 +19274,770 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + rsp_params = (struct mc_rsp_api_ver *)cmd->params; + *major_ver = le16_to_cpu(rsp_params->major_ver); + *minor_ver = le16_to_cpu(rsp_params->minor_ver); - } - - #endif /* __FSL_MC_CMD_H */ ---- a/drivers/staging/fsl-mc/include/mc-sys.h -+++ b/drivers/staging/fsl-mc/include/mc-sys.h -@@ -1,4 +1,5 @@ --/* Copyright 2013-2014 Freescale Semiconductor Inc. ++} ++ ++/** ++ * Bit masks for a MC I/O object (struct fsl_mc_io) flags ++ */ ++#define FSL_MC_IO_ATOMIC_CONTEXT_PORTAL 0x0001 ++ ++/** ++ * struct fsl_mc_io - MC I/O object to be passed-in to mc_send_command() ++ * @dev: device associated with this Mc I/O object ++ * @flags: flags for mc_send_command() ++ * @portal_size: MC command portal size in bytes ++ * @portal_phys_addr: MC command portal physical address ++ * @portal_virt_addr: MC command portal virtual address ++ * @dpmcp_dev: pointer to the DPMCP device associated with the MC portal. ++ * ++ * Fields are only meaningful if the FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is not ++ * set: ++ * @mutex: Mutex to serialize mc_send_command() calls that use the same MC ++ * portal, if the fsl_mc_io object was created with the ++ * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag off. mc_send_command() calls for this ++ * fsl_mc_io object must be made only from non-atomic context. ++ * ++ * Fields are only meaningful if the FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is ++ * set: ++ * @spinlock: Spinlock to serialize mc_send_command() calls that use the same MC ++ * portal, if the fsl_mc_io object was created with the ++ * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag on. mc_send_command() calls for this ++ * fsl_mc_io object can be made from atomic or non-atomic context. ++ */ ++struct fsl_mc_io { ++ struct device *dev; ++ u16 flags; ++ u32 portal_size; ++ phys_addr_t portal_phys_addr; ++ void __iomem *portal_virt_addr; ++ struct fsl_mc_device *dpmcp_dev; ++ union { ++ /* ++ * This field is only meaningful if the ++ * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is not set ++ */ ++ struct mutex mutex; /* serializes mc_send_command() */ ++ ++ /* ++ * This field is only meaningful if the ++ * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is set ++ */ ++ spinlock_t spinlock; /* serializes mc_send_command() */ ++ }; ++}; ++ ++int mc_send_command(struct fsl_mc_io *mc_io, struct fsl_mc_command *cmd); ++ ++#ifdef CONFIG_FSL_MC_BUS ++#define dev_is_fsl_mc(_dev) ((_dev)->bus == &fsl_mc_bus_type) ++#else ++/* If fsl-mc bus is not present device cannot belong to fsl-mc bus */ ++#define dev_is_fsl_mc(_dev) (0) ++#endif ++ ++/* Macro to check if a device is a container device */ ++#define fsl_mc_is_cont_dev(_dev) (to_fsl_mc_device(_dev)->flags & \ ++ FSL_MC_IS_DPRC) ++ ++/* Macro to get the container device of a MC device */ ++#define fsl_mc_cont_dev(_dev) (fsl_mc_is_cont_dev(_dev) ? \ ++ (_dev) : (_dev)->parent) ++ ++#define fsl_mc_is_dev_coherent(_dev) \ ++ (!((to_fsl_mc_device(_dev))->obj_desc.flags & \ ++ FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY)) ++ +/* -+ * Copyright 2013-2016 Freescale Semiconductor Inc. - * - * Interface of the I/O services to send MC commands to the MC hardware - * ---- a/drivers/staging/fsl-mc/include/mc.h -+++ b/drivers/staging/fsl-mc/include/mc.h -@@ -1,7 +1,7 @@ - /* - * Freescale Management Complex (MC) bus public interface - * -- * Copyright (C) 2014 Freescale Semiconductor, Inc. -+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. - * Author: German Rivera <German.Rivera@freescale.com> - * - * This file is licensed under the terms of the GNU General Public -@@ -81,7 +81,7 @@ enum fsl_mc_pool_type { - */ - struct fsl_mc_resource { - enum fsl_mc_pool_type type; -- int32_t id; -+ s32 id; - void *data; - struct fsl_mc_resource_pool *parent_pool; - struct list_head node; -@@ -122,6 +122,7 @@ struct fsl_mc_device_irq { - * @regions: pointer to array of MMIO region entries - * @irqs: pointer to array of pointers to interrupts allocated to this device - * @resource: generic resource associated with this MC object device, if any. -+ * @driver_override: Driver name to force a match - * - * Generic device object for MC object devices that are "attached" to a - * MC bus. -@@ -154,6 +155,7 @@ struct fsl_mc_device { - struct resource *regions; - struct fsl_mc_device_irq **irqs; - struct fsl_mc_resource *resource; -+ const char *driver_override; - }; - - #define to_fsl_mc_device(_dev) \ -@@ -175,6 +177,8 @@ struct fsl_mc_device { - #define fsl_mc_driver_register(drv) \ - __fsl_mc_driver_register(drv, THIS_MODULE) - ++ * module_fsl_mc_driver() - Helper macro for drivers that don't do ++ * anything special in module init/exit. This eliminates a lot of ++ * boilerplate. Each module may only use this macro once, and ++ * calling it replaces module_init() and module_exit() ++ */ ++#define module_fsl_mc_driver(__fsl_mc_driver) \ ++ module_driver(__fsl_mc_driver, fsl_mc_driver_register, \ ++ fsl_mc_driver_unregister) ++ +void fsl_mc_device_remove(struct fsl_mc_device *mc_dev); + - int __must_check __fsl_mc_driver_register(struct fsl_mc_driver *fsl_mc_driver, - struct module *owner); - -@@ -198,4 +202,13 @@ int __must_check fsl_mc_allocate_irqs(st - - void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev); - ++/* ++ * Macro to avoid include chaining to get THIS_MODULE ++ */ ++#define fsl_mc_driver_register(drv) \ ++ __fsl_mc_driver_register(drv, THIS_MODULE) ++ ++int __must_check __fsl_mc_driver_register(struct fsl_mc_driver *fsl_mc_driver, ++ struct module *owner); ++ ++void fsl_mc_driver_unregister(struct fsl_mc_driver *driver); ++ ++int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, ++ u16 mc_io_flags, ++ struct fsl_mc_io **new_mc_io); ++ ++void fsl_mc_portal_free(struct fsl_mc_io *mc_io); ++ ++int fsl_mc_portal_reset(struct fsl_mc_io *mc_io); ++ ++int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev, ++ enum fsl_mc_pool_type pool_type, ++ struct fsl_mc_device **new_mc_adev); ++ ++void fsl_mc_object_free(struct fsl_mc_device *mc_adev); ++ ++struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, ++ struct msi_domain_info *info, ++ struct irq_domain *parent); ++ ++int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev); ++ ++void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev); ++ +void fsl_mc_dma_configure(struct fsl_mc_device *mc_dev, + struct device_node *fsl_mc_platform_node, int coherent); + -+#ifdef CONFIG_FSL_MC_BUS -+struct iommu_group *fsl_mc_device_group(struct device *dev); -+#else -+#define fsl_mc_device_group(__dev) NULL -+#endif ++extern struct bus_type fsl_mc_bus_type; ++ ++extern struct device_type fsl_mc_bus_dprc_type; ++extern struct device_type fsl_mc_bus_dpni_type; ++extern struct device_type fsl_mc_bus_dpio_type; ++extern struct device_type fsl_mc_bus_dpsw_type; ++extern struct device_type fsl_mc_bus_dpdmux_type; ++extern struct device_type fsl_mc_bus_dpbp_type; ++extern struct device_type fsl_mc_bus_dpcon_type; ++extern struct device_type fsl_mc_bus_dpmcp_type; ++extern struct device_type fsl_mc_bus_dpmac_type; ++extern struct device_type fsl_mc_bus_dprtc_type; ++extern struct device_type fsl_mc_bus_dpseci_type; ++extern struct device_type fsl_mc_bus_dpdcei_type; ++extern struct device_type fsl_mc_bus_dpaiop_type; ++extern struct device_type fsl_mc_bus_dpci_type; ++extern struct device_type fsl_mc_bus_dpdmai_type; ++ ++static inline bool is_fsl_mc_bus_dprc(const struct fsl_mc_device *mc_dev) ++{ ++ return mc_dev->dev.type == &fsl_mc_bus_dprc_type; ++} ++ ++static inline bool is_fsl_mc_bus_dpni(const struct fsl_mc_device *mc_dev) ++{ ++ return mc_dev->dev.type == &fsl_mc_bus_dpni_type; ++} ++ ++static inline bool is_fsl_mc_bus_dpio(const struct fsl_mc_device *mc_dev) ++{ ++ return mc_dev->dev.type == &fsl_mc_bus_dpio_type; ++} ++ ++static inline bool is_fsl_mc_bus_dpsw(const struct fsl_mc_device *mc_dev) ++{ ++ return mc_dev->dev.type == &fsl_mc_bus_dpsw_type; ++} ++ ++static inline bool is_fsl_mc_bus_dpdmux(const struct fsl_mc_device *mc_dev) ++{ ++ return mc_dev->dev.type == &fsl_mc_bus_dpdmux_type; ++} ++ ++static inline bool is_fsl_mc_bus_dpbp(const struct fsl_mc_device *mc_dev) ++{ ++ return mc_dev->dev.type == &fsl_mc_bus_dpbp_type; ++} ++ ++static inline bool is_fsl_mc_bus_dpcon(const struct fsl_mc_device *mc_dev) ++{ ++ return mc_dev->dev.type == &fsl_mc_bus_dpcon_type; ++} ++ ++static inline bool is_fsl_mc_bus_dpmcp(const struct fsl_mc_device *mc_dev) ++{ ++ return mc_dev->dev.type == &fsl_mc_bus_dpmcp_type; ++} ++ ++static inline bool is_fsl_mc_bus_dpmac(const struct fsl_mc_device *mc_dev) ++{ ++ return mc_dev->dev.type == &fsl_mc_bus_dpmac_type; ++} ++ ++static inline bool is_fsl_mc_bus_dprtc(const struct fsl_mc_device *mc_dev) ++{ ++ return mc_dev->dev.type == &fsl_mc_bus_dprtc_type; ++} ++ ++static inline bool is_fsl_mc_bus_dpseci(const struct fsl_mc_device *mc_dev) ++{ ++ return mc_dev->dev.type == &fsl_mc_bus_dpseci_type; ++} ++ ++static inline bool is_fsl_mc_bus_dpdcei(const struct fsl_mc_device *mc_dev) ++{ ++ return mc_dev->dev.type == &fsl_mc_bus_dpdcei_type; ++} ++ ++static inline bool is_fsl_mc_bus_dpaiop(const struct fsl_mc_device *mc_dev) ++{ ++ return mc_dev->dev.type == &fsl_mc_bus_dpaiop_type; ++} ++ ++static inline bool is_fsl_mc_bus_dpci(const struct fsl_mc_device *mc_dev) ++{ ++ return mc_dev->dev.type == &fsl_mc_bus_dpci_type; ++} ++ ++static inline bool is_fsl_mc_bus_dpdmai(const struct fsl_mc_device *mc_dev) ++{ ++ return mc_dev->dev.type == &fsl_mc_bus_dpdmai_type; ++} ++ ++/* ++ * Data Path Resource Container (DPRC) API ++ */ ++ ++/* Minimal supported DPRC Version */ ++#define DPRC_MIN_VER_MAJOR 6 ++#define DPRC_MIN_VER_MINOR 0 ++ ++/* DPRC command versioning */ ++#define DPRC_CMD_BASE_VERSION 1 ++#define DPRC_CMD_ID_OFFSET 4 ++ ++#define DPRC_CMD(id) (((id) << DPRC_CMD_ID_OFFSET) | DPRC_CMD_BASE_VERSION) ++ ++/* DPRC command IDs */ ++#define DPRC_CMDID_CLOSE DPRC_CMD(0x800) ++#define DPRC_CMDID_OPEN DPRC_CMD(0x805) ++#define DPRC_CMDID_GET_API_VERSION DPRC_CMD(0xa05) ++ ++#define DPRC_CMDID_GET_ATTR DPRC_CMD(0x004) ++#define DPRC_CMDID_RESET_CONT DPRC_CMD(0x005) ++ ++#define DPRC_CMDID_SET_IRQ DPRC_CMD(0x010) ++#define DPRC_CMDID_SET_IRQ_ENABLE DPRC_CMD(0x012) ++#define DPRC_CMDID_SET_IRQ_MASK DPRC_CMD(0x014) ++#define DPRC_CMDID_GET_IRQ_STATUS DPRC_CMD(0x016) ++#define DPRC_CMDID_CLEAR_IRQ_STATUS DPRC_CMD(0x017) ++ ++#define DPRC_CMDID_GET_CONT_ID DPRC_CMD(0x830) ++#define DPRC_CMDID_GET_OBJ_COUNT DPRC_CMD(0x159) ++#define DPRC_CMDID_GET_OBJ DPRC_CMD(0x15A) ++#define DPRC_CMDID_GET_OBJ_REG DPRC_CMD(0x15E) ++#define DPRC_CMDID_SET_OBJ_IRQ DPRC_CMD(0x15F) ++ ++struct dprc_cmd_open { ++ __le32 container_id; ++}; ++ ++struct dprc_cmd_reset_container { ++ __le32 child_container_id; ++}; ++ ++struct dprc_cmd_set_irq { ++ /* cmd word 0 */ ++ __le32 irq_val; ++ u8 irq_index; ++ u8 pad[3]; ++ /* cmd word 1 */ ++ __le64 irq_addr; ++ /* cmd word 2 */ ++ __le32 irq_num; ++}; ++ ++#define DPRC_ENABLE 0x1 ++ ++struct dprc_cmd_set_irq_enable { ++ u8 enable; ++ u8 pad[3]; ++ u8 irq_index; ++}; ++ ++struct dprc_cmd_set_irq_mask { ++ __le32 mask; ++ u8 irq_index; ++}; ++ ++struct dprc_cmd_get_irq_status { ++ __le32 status; ++ u8 irq_index; ++}; ++ ++struct dprc_rsp_get_irq_status { ++ __le32 status; ++}; ++ ++struct dprc_cmd_clear_irq_status { ++ __le32 status; ++ u8 irq_index; ++}; ++ ++struct dprc_rsp_get_attributes { ++ /* response word 0 */ ++ __le32 container_id; ++ __le32 icid; ++ /* response word 1 */ ++ __le32 options; ++ __le32 portal_id; ++}; ++ ++struct dprc_rsp_get_obj_count { ++ __le32 pad; ++ __le32 obj_count; ++}; ++ ++struct dprc_cmd_get_obj { ++ __le32 obj_index; ++}; ++ ++struct dprc_rsp_get_obj { ++ /* response word 0 */ ++ __le32 pad0; ++ __le32 id; ++ /* response word 1 */ ++ __le16 vendor; ++ u8 irq_count; ++ u8 region_count; ++ __le32 state; ++ /* response word 2 */ ++ __le16 version_major; ++ __le16 version_minor; ++ __le16 flags; ++ __le16 pad1; ++ /* response word 3-4 */ ++ u8 type[16]; ++ /* response word 5-6 */ ++ u8 label[16]; ++}; ++ ++struct dprc_cmd_get_obj_region { ++ /* cmd word 0 */ ++ __le32 obj_id; ++ __le16 pad0; ++ u8 region_index; ++ u8 pad1; ++ /* cmd word 1-2 */ ++ __le64 pad2[2]; ++ /* cmd word 3-4 */ ++ u8 obj_type[16]; ++}; ++ ++struct dprc_rsp_get_obj_region { ++ /* response word 0 */ ++ __le64 pad0; ++ /* response word 1 */ ++ __le32 base_addr; ++ __le32 pad1; ++ /* response word 2 */ ++ __le32 size; ++ u8 type; ++ u8 pad2[3]; ++ /* response word 3 */ ++ __le32 flags; ++}; ++ ++struct dprc_cmd_set_obj_irq { ++ /* cmd word 0 */ ++ __le32 irq_val; ++ u8 irq_index; ++ u8 pad[3]; ++ /* cmd word 1 */ ++ __le64 irq_addr; ++ /* cmd word 2 */ ++ __le32 irq_num; ++ __le32 obj_id; ++ /* cmd word 3-4 */ ++ u8 obj_type[16]; ++}; ++ ++/* ++ * DPRC API for managing and querying DPAA resources ++ */ ++int dprc_open(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ int container_id, ++ u16 *token); ++ ++int dprc_close(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token); ++ ++/* DPRC IRQ events */ ++ ++/* IRQ event - Indicates that a new object added to the container */ ++#define DPRC_IRQ_EVENT_OBJ_ADDED 0x00000001 ++/* IRQ event - Indicates that an object was removed from the container */ ++#define DPRC_IRQ_EVENT_OBJ_REMOVED 0x00000002 ++/* ++ * IRQ event - Indicates that one of the descendant containers that opened by ++ * this container is destroyed ++ */ ++#define DPRC_IRQ_EVENT_CONTAINER_DESTROYED 0x00000010 ++ ++/* ++ * IRQ event - Indicates that on one of the container's opened object is ++ * destroyed ++ */ ++#define DPRC_IRQ_EVENT_OBJ_DESTROYED 0x00000020 ++ ++/* Irq event - Indicates that object is created at the container */ ++#define DPRC_IRQ_EVENT_OBJ_CREATED 0x00000040 ++ ++/** ++ * struct dprc_irq_cfg - IRQ configuration ++ * @paddr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dprc_irq_cfg { ++ phys_addr_t paddr; ++ u32 val; ++ int irq_num; ++}; ++ ++int dprc_set_irq(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ u8 irq_index, ++ struct dprc_irq_cfg *irq_cfg); ++ ++int dprc_set_irq_enable(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ u8 irq_index, ++ u8 en); ++ ++int dprc_set_irq_mask(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ u8 irq_index, ++ u32 mask); ++ ++int dprc_get_irq_status(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ u8 irq_index, ++ u32 *status); ++ ++int dprc_clear_irq_status(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ u8 irq_index, ++ u32 status); ++ ++/** ++ * struct dprc_attributes - Container attributes ++ * @container_id: Container's ID ++ * @icid: Container's ICID ++ * @portal_id: Container's portal ID ++ * @options: Container's options as set at container's creation ++ */ ++struct dprc_attributes { ++ int container_id; ++ u32 icid; ++ int portal_id; ++ u64 options; ++}; ++ ++int dprc_get_attributes(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ struct dprc_attributes *attributes); ++ ++int dprc_get_obj_count(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ int *obj_count); ++ ++int dprc_get_obj(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ int obj_index, ++ struct fsl_mc_obj_desc *obj_desc); ++ ++int dprc_set_obj_irq(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ char *obj_type, ++ int obj_id, ++ u8 irq_index, ++ struct dprc_irq_cfg *irq_cfg); ++ ++/* Region flags */ ++/* Cacheable - Indicates that region should be mapped as cacheable */ ++#define DPRC_REGION_CACHEABLE 0x00000001 ++ ++/** ++ * enum dprc_region_type - Region type ++ * @DPRC_REGION_TYPE_MC_PORTAL: MC portal region ++ * @DPRC_REGION_TYPE_QBMAN_PORTAL: Qbman portal region ++ */ ++enum dprc_region_type { ++ DPRC_REGION_TYPE_MC_PORTAL, ++ DPRC_REGION_TYPE_QBMAN_PORTAL ++}; ++ ++#define DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY 0x0001 ++ ++/** ++ * struct dprc_region_desc - Mappable region descriptor ++ * @base_offset: Region offset from region's base address. ++ * For DPMCP and DPRC objects, region base is offset from SoC MC portals ++ * base address; For DPIO, region base is offset from SoC QMan portals ++ * base address ++ * @size: Region size (in bytes) ++ * @flags: Region attributes ++ * @type: Portal region type ++ */ ++struct dprc_region_desc { ++ u32 base_offset; ++ u32 size; ++ u32 flags; ++ enum dprc_region_type type; ++}; ++ ++int dprc_get_obj_region(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ char *obj_type, ++ int obj_id, ++ u8 region_index, ++ struct dprc_region_desc *region_desc); ++ ++int dprc_get_api_version(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 *major_ver, ++ u16 *minor_ver); ++ ++int dprc_get_container_id(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ int *container_id); ++ ++int dprc_reset_container(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ int child_container_id); ++ ++/* ++ * Data Path Buffer Pool (DPBP) API ++ * Contains initialization APIs and runtime control APIs for DPBP ++ */ ++ ++int dpbp_open(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ int dpbp_id, ++ u16 *token); ++ ++int dpbp_close(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token); ++ ++int dpbp_enable(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token); ++ ++int dpbp_disable(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token); ++ ++int dpbp_reset(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token); ++ ++/** ++ * struct dpbp_attr - Structure representing DPBP attributes ++ * @id: DPBP object ID ++ * @bpid: Hardware buffer pool ID; should be used as an argument in ++ * acquire/release operations on buffers ++ */ ++struct dpbp_attr { ++ int id; ++ u16 bpid; ++}; ++ ++int dpbp_get_attributes(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ struct dpbp_attr *attr); ++ ++/* Data Path Concentrator (DPCON) API ++ * Contains initialization APIs and runtime control APIs for DPCON ++ */ ++ ++/** ++ * Use it to disable notifications; see dpcon_set_notification() ++ */ ++#define DPCON_INVALID_DPIO_ID (int)(-1) ++ ++int dpcon_open(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ int dpcon_id, ++ u16 *token); ++ ++int dpcon_close(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token); ++ ++int dpcon_enable(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token); ++ ++int dpcon_disable(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token); ++ ++int dpcon_reset(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token); ++ ++/** ++ * struct dpcon_attr - Structure representing DPCON attributes ++ * @id: DPCON object ID ++ * @qbman_ch_id: Channel ID to be used by dequeue operation ++ * @num_priorities: Number of priorities for the DPCON channel (1-8) ++ */ ++struct dpcon_attr { ++ int id; ++ u16 qbman_ch_id; ++ u8 num_priorities; ++}; ++ ++int dpcon_get_attributes(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ struct dpcon_attr *attr); ++ ++/** ++ * struct dpcon_notification_cfg - Structure representing notification params ++ * @dpio_id: DPIO object ID; must be configured with a notification channel; ++ * to disable notifications set it to 'DPCON_INVALID_DPIO_ID'; ++ * @priority: Priority selection within the DPIO channel; valid values ++ * are 0-7, depending on the number of priorities in that channel ++ * @user_ctx: User context value provided with each CDAN message ++ */ ++struct dpcon_notification_cfg { ++ int dpio_id; ++ u8 priority; ++ u64 user_ctx; ++}; ++ ++int dpcon_set_notification(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ struct dpcon_notification_cfg *cfg); ++ ++struct irq_domain; ++struct msi_domain_info; ++ ++/** ++ * Maximum number of total IRQs that can be pre-allocated for an MC bus' ++ * IRQ pool ++ */ ++#define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256 ++ ++/** ++ * struct fsl_mc_resource_pool - Pool of MC resources of a given ++ * type ++ * @type: type of resources in the pool ++ * @max_count: maximum number of resources in the pool ++ * @free_count: number of free resources in the pool ++ * @mutex: mutex to serialize access to the pool's free list ++ * @free_list: anchor node of list of free resources in the pool ++ * @mc_bus: pointer to the MC bus that owns this resource pool ++ */ ++struct fsl_mc_resource_pool { ++ enum fsl_mc_pool_type type; ++ int max_count; ++ int free_count; ++ struct mutex mutex; /* serializes access to free_list */ ++ struct list_head free_list; ++ struct fsl_mc_bus *mc_bus; ++}; ++ ++/** ++ * struct fsl_mc_restool - information associated with a restool device file ++ * @cdev: struct char device linked to the root dprc ++ * @dev: dev_t for the char device to be added ++ * @device: newly created device in /dev ++ * @mutex: mutex lock to serialize the open/release operations ++ * @local_instance_in_use: local MC I/O instance in use or not ++ * @dynamic_instance_count: number of dynamically created MC I/O instances ++ */ ++struct fsl_mc_restool { ++ struct cdev cdev; ++ dev_t dev; ++ struct device *device; ++ struct mutex mutex; /* serialize open/release operations */ ++ bool local_instance_in_use; ++ u32 dynamic_instance_count; ++}; ++ ++/** ++ * struct fsl_mc_bus - logical bus that corresponds to a physical DPRC ++ * @mc_dev: fsl-mc device for the bus device itself. ++ * @resource_pools: array of resource pools (one pool per resource type) ++ * for this MC bus. These resources represent allocatable entities ++ * from the physical DPRC. ++ * @irq_resources: Pointer to array of IRQ objects for the IRQ pool ++ * @scan_mutex: Serializes bus scanning ++ * @dprc_attr: DPRC attributes ++ * @restool_misc: struct that abstracts the interaction with userspace restool ++ */ ++struct fsl_mc_bus { ++ struct fsl_mc_device mc_dev; ++ struct fsl_mc_resource_pool resource_pools[FSL_MC_NUM_POOL_TYPES]; ++ struct fsl_mc_device_irq *irq_resources; ++ struct mutex scan_mutex; /* serializes bus scanning */ ++ struct dprc_attributes dprc_attr; ++ struct fsl_mc_restool restool_misc; ++}; ++ ++int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, ++ const char *driver_override, ++ unsigned int *total_irq_count); ++ ++int fsl_mc_find_msi_domain(struct device *mc_platform_dev, ++ struct irq_domain **mc_msi_domain); ++ ++int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, ++ unsigned int irq_count); ++ ++void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus); ++ ++void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev); ++ ++void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev); ++ ++void fsl_mc_get_root_dprc(struct device *dev, struct device **root_dprc_dev); ++ ++#endif /* _FSL_MC_H_ */ +--- /dev/null ++++ b/include/uapi/linux/fsl_mc.h +@@ -0,0 +1,31 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++/* ++ * Management Complex (MC) userspace public interface ++ * ++ * Copyright 2018 NXP ++ * ++ */ ++#ifndef _UAPI_FSL_MC_H_ ++#define _UAPI_FSL_MC_H_ ++ ++#define MC_CMD_NUM_OF_PARAMS 7 ++ ++/** ++ * struct fsl_mc_command - Management Complex (MC) command structure ++ * @header: MC command header ++ * @params: MC command parameters ++ * ++ * Used by RESTOOL_SEND_MC_COMMAND ++ */ ++struct fsl_mc_command { ++ __u64 header; ++ __u64 params[MC_CMD_NUM_OF_PARAMS]; ++}; ++ ++#define RESTOOL_IOCTL_TYPE 'R' ++#define RESTOOL_IOCTL_SEQ 0xE0 ++ ++#define RESTOOL_SEND_MC_COMMAND \ ++ _IOWR(RESTOOL_IOCTL_TYPE, RESTOOL_IOCTL_SEQ, struct fsl_mc_command) + - #endif /* _FSL_MC_H_ */ ++#endif /* _UAPI_FSL_MC_H_ */ diff --git a/target/linux/layerscape/patches-4.9/705-dpaa2-support-layerscape.patch b/target/linux/layerscape/patches-4.9/705-dpaa2-support-layerscape.patch index 5363f0a356..23e4ff9202 100644 --- a/target/linux/layerscape/patches-4.9/705-dpaa2-support-layerscape.patch +++ b/target/linux/layerscape/patches-4.9/705-dpaa2-support-layerscape.patch @@ -1,6 +1,6 @@ -From e729e648e4259940473e256dd4f9c8df99e774b0 Mon Sep 17 00:00:00 2001 +From 77cc39e936f87463f92f7fddaaf0de51eec3972f Mon Sep 17 00:00:00 2001 From: Yangbo Lu <yangbo.lu@nxp.com> -Date: Wed, 17 Jan 2018 15:12:58 +0800 +Date: Fri, 6 Jul 2018 15:30:21 +0800 Subject: [PATCH] dpaa2: support layerscape This is an integrated patch for layerscape dpaa2 support. @@ -13,51 +13,61 @@ Signed-off-by: Catalin Horghidan <catalin.horghidan@nxp.com> Signed-off-by: Mathew McBride <matt@traverse.com.au> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- - drivers/soc/fsl/ls2-console/Kconfig | 4 + - drivers/soc/fsl/ls2-console/Makefile | 1 + - drivers/soc/fsl/ls2-console/ls2-console.c | 284 ++ - drivers/staging/fsl-dpaa2/ethernet/Makefile | 11 + - drivers/staging/fsl-dpaa2/ethernet/README | 186 ++ - .../staging/fsl-dpaa2/ethernet/dpaa2-eth-debugfs.c | 352 ++ - .../staging/fsl-dpaa2/ethernet/dpaa2-eth-debugfs.h | 60 + - .../staging/fsl-dpaa2/ethernet/dpaa2-eth-trace.h | 184 + - drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c | 3516 ++++++++++++++++++++ - drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h | 499 +++ - drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c | 864 +++++ - drivers/staging/fsl-dpaa2/ethernet/dpkg.h | 176 + - drivers/staging/fsl-dpaa2/ethernet/dpni-cmd.h | 658 ++++ - drivers/staging/fsl-dpaa2/ethernet/dpni.c | 1903 +++++++++++ - drivers/staging/fsl-dpaa2/ethernet/dpni.h | 1053 ++++++ - drivers/staging/fsl-dpaa2/ethernet/net.h | 480 +++ - drivers/staging/fsl-dpaa2/ethsw/Kconfig | 6 + - drivers/staging/fsl-dpaa2/ethsw/Makefile | 10 + - drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h | 851 +++++ - drivers/staging/fsl-dpaa2/ethsw/dpsw.c | 2762 +++++++++++++++ - drivers/staging/fsl-dpaa2/ethsw/dpsw.h | 1269 +++++++ - drivers/staging/fsl-dpaa2/ethsw/switch.c | 1857 +++++++++++ - drivers/staging/fsl-dpaa2/evb/Kconfig | 7 + - drivers/staging/fsl-dpaa2/evb/Makefile | 10 + - drivers/staging/fsl-dpaa2/evb/dpdmux-cmd.h | 279 ++ - drivers/staging/fsl-dpaa2/evb/dpdmux.c | 1112 +++++++ - drivers/staging/fsl-dpaa2/evb/dpdmux.h | 453 +++ - drivers/staging/fsl-dpaa2/evb/evb.c | 1350 ++++++++ - drivers/staging/fsl-dpaa2/mac/Kconfig | 23 + - drivers/staging/fsl-dpaa2/mac/Makefile | 10 + - drivers/staging/fsl-dpaa2/mac/dpmac-cmd.h | 172 + - drivers/staging/fsl-dpaa2/mac/dpmac.c | 620 ++++ - drivers/staging/fsl-dpaa2/mac/dpmac.h | 342 ++ - drivers/staging/fsl-dpaa2/mac/mac.c | 670 ++++ - drivers/staging/fsl-dpaa2/rtc/Makefile | 10 + - drivers/staging/fsl-dpaa2/rtc/dprtc-cmd.h | 160 + - drivers/staging/fsl-dpaa2/rtc/dprtc.c | 746 +++++ - drivers/staging/fsl-dpaa2/rtc/dprtc.h | 172 + - drivers/staging/fsl-dpaa2/rtc/rtc.c | 243 ++ - 39 files changed, 23365 insertions(+) + drivers/soc/fsl/ls2-console/Kconfig | 4 + + drivers/soc/fsl/ls2-console/Makefile | 1 + + drivers/soc/fsl/ls2-console/ls2-console.c | 284 ++ + drivers/staging/fsl-dpaa2/ethernet/Makefile | 12 + + drivers/staging/fsl-dpaa2/ethernet/README | 186 + + drivers/staging/fsl-dpaa2/ethernet/TODO | 18 + + .../fsl-dpaa2/ethernet/dpaa2-eth-ceetm.c | 1253 ++++++ + .../fsl-dpaa2/ethernet/dpaa2-eth-ceetm.h | 182 + + .../fsl-dpaa2/ethernet/dpaa2-eth-debugfs.c | 357 ++ + .../fsl-dpaa2/ethernet/dpaa2-eth-debugfs.h | 60 + + .../fsl-dpaa2/ethernet/dpaa2-eth-trace.h | 185 + + .../staging/fsl-dpaa2/ethernet/dpaa2-eth.c | 3734 +++++++++++++++++ + .../staging/fsl-dpaa2/ethernet/dpaa2-eth.h | 601 +++ + .../fsl-dpaa2/ethernet/dpaa2-ethtool.c | 878 ++++ + drivers/staging/fsl-dpaa2/ethernet/dpkg.h | 176 + + drivers/staging/fsl-dpaa2/ethernet/dpni-cmd.h | 719 ++++ + drivers/staging/fsl-dpaa2/ethernet/dpni.c | 2112 ++++++++++ + drivers/staging/fsl-dpaa2/ethernet/dpni.h | 1172 ++++++ + drivers/staging/fsl-dpaa2/ethernet/net.h | 480 +++ + drivers/staging/fsl-dpaa2/ethsw/Makefile | 10 + + drivers/staging/fsl-dpaa2/ethsw/README | 106 + + drivers/staging/fsl-dpaa2/ethsw/TODO | 14 + + drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h | 359 ++ + drivers/staging/fsl-dpaa2/ethsw/dpsw.c | 1165 +++++ + drivers/staging/fsl-dpaa2/ethsw/dpsw.h | 592 +++ + .../staging/fsl-dpaa2/ethsw/ethsw-ethtool.c | 206 + + drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 1438 +++++++ + drivers/staging/fsl-dpaa2/ethsw/ethsw.h | 90 + + drivers/staging/fsl-dpaa2/evb/Kconfig | 7 + + drivers/staging/fsl-dpaa2/evb/Makefile | 10 + + drivers/staging/fsl-dpaa2/evb/dpdmux-cmd.h | 279 ++ + drivers/staging/fsl-dpaa2/evb/dpdmux.c | 1111 +++++ + drivers/staging/fsl-dpaa2/evb/dpdmux.h | 453 ++ + drivers/staging/fsl-dpaa2/evb/evb.c | 1354 ++++++ + drivers/staging/fsl-dpaa2/mac/Kconfig | 23 + + drivers/staging/fsl-dpaa2/mac/Makefile | 10 + + drivers/staging/fsl-dpaa2/mac/dpmac-cmd.h | 172 + + drivers/staging/fsl-dpaa2/mac/dpmac.c | 619 +++ + drivers/staging/fsl-dpaa2/mac/dpmac.h | 342 ++ + drivers/staging/fsl-dpaa2/mac/mac.c | 673 +++ + drivers/staging/fsl-dpaa2/rtc/Makefile | 10 + + drivers/staging/fsl-dpaa2/rtc/dprtc-cmd.h | 160 + + drivers/staging/fsl-dpaa2/rtc/dprtc.c | 746 ++++ + drivers/staging/fsl-dpaa2/rtc/dprtc.h | 172 + + drivers/staging/fsl-dpaa2/rtc/rtc.c | 242 ++ + include/linux/filter.h | 3 + + 46 files changed, 22780 insertions(+) create mode 100644 drivers/soc/fsl/ls2-console/Kconfig create mode 100644 drivers/soc/fsl/ls2-console/Makefile create mode 100644 drivers/soc/fsl/ls2-console/ls2-console.c create mode 100644 drivers/staging/fsl-dpaa2/ethernet/Makefile create mode 100644 drivers/staging/fsl-dpaa2/ethernet/README + create mode 100644 drivers/staging/fsl-dpaa2/ethernet/TODO + create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-ceetm.c + create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-ceetm.h create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-debugfs.c create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-debugfs.h create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-trace.h @@ -69,12 +79,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpni.c create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpni.h create mode 100644 drivers/staging/fsl-dpaa2/ethernet/net.h - create mode 100644 drivers/staging/fsl-dpaa2/ethsw/Kconfig create mode 100644 drivers/staging/fsl-dpaa2/ethsw/Makefile + create mode 100644 drivers/staging/fsl-dpaa2/ethsw/README + create mode 100644 drivers/staging/fsl-dpaa2/ethsw/TODO create mode 100644 drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h create mode 100644 drivers/staging/fsl-dpaa2/ethsw/dpsw.c create mode 100644 drivers/staging/fsl-dpaa2/ethsw/dpsw.h - create mode 100644 drivers/staging/fsl-dpaa2/ethsw/switch.c + create mode 100644 drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c + create mode 100644 drivers/staging/fsl-dpaa2/ethsw/ethsw.c + create mode 100644 drivers/staging/fsl-dpaa2/ethsw/ethsw.h create mode 100644 drivers/staging/fsl-dpaa2/evb/Kconfig create mode 100644 drivers/staging/fsl-dpaa2/evb/Makefile create mode 100644 drivers/staging/fsl-dpaa2/evb/dpdmux-cmd.h @@ -393,7 +406,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +MODULE_DESCRIPTION("Freescale LS2 console driver"); --- /dev/null +++ b/drivers/staging/fsl-dpaa2/ethernet/Makefile -@@ -0,0 +1,11 @@ +@@ -0,0 +1,12 @@ +# +# Makefile for the Freescale DPAA2 Ethernet controller +# @@ -402,6 +415,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +fsl-dpaa2-eth-objs := dpaa2-eth.o dpaa2-ethtool.o dpni.o +fsl-dpaa2-eth-${CONFIG_FSL_DPAA2_ETH_DEBUGFS} += dpaa2-eth-debugfs.o ++fsl-dpaa2-eth-${CONFIG_FSL_DPAA2_ETH_CEETM} += dpaa2-eth-ceetm.o + +# Needed by the tracing framework +CFLAGS_dpaa2-eth.o := -I$(src) @@ -595,8 +609,1470 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +Hardware specific statistics for the network interface as well as some +non-standard driver stats can be consulted through ethtool -S option. --- /dev/null ++++ b/drivers/staging/fsl-dpaa2/ethernet/TODO +@@ -0,0 +1,18 @@ ++* Add a DPAA2 MAC kernel driver in order to allow PHY management; currently ++ the DPMAC objects and their link to DPNIs are handled by MC internally ++ and all PHYs are seen as fixed-link ++* add more debug support: decide how to expose detailed debug statistics, ++ add ingress error queue support ++* MC firmware uprev; the DPAA2 objects used by the Ethernet driver need to ++ be kept in sync with binary interface changes in MC ++* refine README file ++* cleanup ++ ++NOTE: None of the above is must-have before getting the DPAA2 Ethernet driver ++out of staging. The main requirement for that is to have the drivers it ++depends on, fsl-mc bus and DPIO driver, moved to drivers/bus and drivers/soc ++respectively. ++ ++ Please send any patches to Greg Kroah-Hartman <gregkh@linuxfoundation.org>, ++ ruxandra.radulescu@nxp.com, devel@driverdev.osuosl.org, ++ linux-kernel@vger.kernel.org +--- /dev/null ++++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-ceetm.c +@@ -0,0 +1,1253 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright 2017 NXP ++ * ++ */ ++ ++#include <linux/init.h> ++#include <linux/module.h> ++ ++#include "dpaa2-eth-ceetm.h" ++#include "dpaa2-eth.h" ++ ++#define DPAA2_CEETM_DESCRIPTION "FSL DPAA2 CEETM qdisc" ++/* Conversion formula from userspace passed Bps to expected Mbit */ ++#define dpaa2_eth_bps_to_mbit(rate) (rate >> 17) ++ ++static const struct nla_policy dpaa2_ceetm_policy[DPAA2_CEETM_TCA_MAX] = { ++ [DPAA2_CEETM_TCA_COPT] = { .len = sizeof(struct dpaa2_ceetm_tc_copt) }, ++ [DPAA2_CEETM_TCA_QOPS] = { .len = sizeof(struct dpaa2_ceetm_tc_qopt) }, ++}; ++ ++struct Qdisc_ops dpaa2_ceetm_qdisc_ops; ++ ++static inline int dpaa2_eth_set_ch_shaping(struct dpaa2_eth_priv *priv, ++ struct dpni_tx_shaping_cfg *scfg, ++ struct dpni_tx_shaping_cfg *ecfg, ++ int coupled, int ch_id) ++{ ++ int err = 0; ++ ++ netdev_dbg(priv->net_dev, "%s: ch_id %d rate %d mbps\n", __func__, ++ ch_id, scfg->rate_limit); ++ err = dpni_set_tx_shaping(priv->mc_io, 0, priv->mc_token, scfg, ++ ecfg, coupled); ++ if (err) ++ netdev_err(priv->net_dev, "dpni_set_tx_shaping err\n"); ++ ++ return err; ++} ++ ++static inline int dpaa2_eth_reset_ch_shaping(struct dpaa2_eth_priv *priv, ++ int ch_id) ++{ ++ struct dpni_tx_shaping_cfg cfg = { 0 }; ++ ++ return dpaa2_eth_set_ch_shaping(priv, &cfg, &cfg, 0, ch_id); ++} ++ ++static inline int ++dpaa2_eth_update_shaping_cfg(struct net_device *dev, ++ struct dpaa2_ceetm_shaping_cfg cfg, ++ struct dpni_tx_shaping_cfg *scfg, ++ struct dpni_tx_shaping_cfg *ecfg) ++{ ++ scfg->rate_limit = dpaa2_eth_bps_to_mbit(cfg.cir); ++ ecfg->rate_limit = dpaa2_eth_bps_to_mbit(cfg.eir); ++ ++ if (cfg.cbs > DPAA2_ETH_MAX_BURST_SIZE) { ++ netdev_err(dev, "Committed burst size must be under %d\n", ++ DPAA2_ETH_MAX_BURST_SIZE); ++ return -EINVAL; ++ } ++ ++ scfg->max_burst_size = cfg.cbs; ++ ++ if (cfg.ebs > DPAA2_ETH_MAX_BURST_SIZE) { ++ netdev_err(dev, "Excess burst size must be under %d\n", ++ DPAA2_ETH_MAX_BURST_SIZE); ++ return -EINVAL; ++ } ++ ++ ecfg->max_burst_size = cfg.ebs; ++ ++ if ((!cfg.cir || !cfg.eir) && cfg.coupled) { ++ netdev_err(dev, "Coupling can be set when both CIR and EIR are finite\n"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++enum update_tx_prio { ++ DPAA2_ETH_ADD_CQ, ++ DPAA2_ETH_DEL_CQ, ++}; ++ ++/* Normalize weights based on max passed value */ ++static inline int dpaa2_eth_normalize_tx_prio(struct dpaa2_ceetm_qdisc *priv) ++{ ++ struct dpni_tx_schedule_cfg *sched_cfg; ++ struct dpaa2_ceetm_class *cl; ++ u32 qpri; ++ u16 weight_max = 0, increment; ++ int i; ++ ++ /* Check the boundaries of the provided values */ ++ for (i = 0; i < priv->clhash.hashsize; i++) ++ hlist_for_each_entry(cl, &priv->clhash.hash[i], common.hnode) ++ weight_max = (weight_max == 0 ? cl->prio.weight : ++ (weight_max < cl->prio.weight ? ++ cl->prio.weight : weight_max)); ++ ++ /* If there are no elements, there's nothing to do */ ++ if (weight_max == 0) ++ return 0; ++ ++ increment = (DPAA2_CEETM_MAX_WEIGHT - DPAA2_CEETM_MIN_WEIGHT) / ++ weight_max; ++ ++ for (i = 0; i < priv->clhash.hashsize; i++) { ++ hlist_for_each_entry(cl, &priv->clhash.hash[i], common.hnode) { ++ if (cl->prio.mode == STRICT_PRIORITY) ++ continue; ++ ++ qpri = cl->prio.qpri; ++ sched_cfg = &priv->prio.tx_prio_cfg.tc_sched[qpri]; ++ ++ sched_cfg->delta_bandwidth = ++ DPAA2_CEETM_MIN_WEIGHT + ++ (cl->prio.weight * increment); ++ ++ pr_debug("%s: Normalized CQ qpri %d weight to %d\n", ++ __func__, qpri, sched_cfg->delta_bandwidth); ++ } ++ } ++ ++ return 0; ++} ++ ++static inline int dpaa2_eth_update_tx_prio(struct dpaa2_eth_priv *priv, ++ struct dpaa2_ceetm_class *cl, ++ enum update_tx_prio type) ++{ ++ struct dpaa2_ceetm_qdisc *sch = qdisc_priv(cl->parent); ++ struct dpni_congestion_notification_cfg notif_cfg = {0}; ++ struct dpni_tx_schedule_cfg *sched_cfg; ++ struct dpni_taildrop td = {0}; ++ u8 ch_id = 0, tc_id = 0; ++ u32 qpri = 0; ++ int err = 0; ++ ++ qpri = cl->prio.qpri; ++ tc_id = DPNI_BUILD_CH_TC(ch_id, qpri); ++ ++ switch (type) { ++ case DPAA2_ETH_ADD_CQ: ++ /* Disable congestion notifications */ ++ notif_cfg.threshold_entry = 0; ++ notif_cfg.threshold_exit = 0; ++ err = dpni_set_congestion_notification(priv->mc_io, 0, ++ priv->mc_token, ++ DPNI_QUEUE_TX, tc_id, ++ ¬if_cfg); ++ if (err) { ++ netdev_err(priv->net_dev, "Error disabling congestion notifications %d\n", ++ err); ++ return err; ++ } ++ /* Enable taildrop */ ++ td.enable = 1; ++ td.units = DPNI_CONGESTION_UNIT_FRAMES; ++ td.threshold = DPAA2_CEETM_TD_THRESHOLD; ++ err = dpni_set_taildrop(priv->mc_io, 0, priv->mc_token, ++ DPNI_CP_GROUP, DPNI_QUEUE_TX, tc_id, ++ 0, &td); ++ if (err) { ++ netdev_err(priv->net_dev, "Error enabling Tx taildrop %d\n", ++ err); ++ return err; ++ } ++ break; ++ case DPAA2_ETH_DEL_CQ: ++ /* Disable taildrop */ ++ td.enable = 0; ++ err = dpni_set_taildrop(priv->mc_io, 0, priv->mc_token, ++ DPNI_CP_GROUP, DPNI_QUEUE_TX, tc_id, ++ 0, &td); ++ if (err) { ++ netdev_err(priv->net_dev, "Error disabling Tx taildrop %d\n", ++ err); ++ return err; ++ } ++ /* Enable congestion notifications */ ++ notif_cfg.units = DPNI_CONGESTION_UNIT_BYTES; ++ notif_cfg.threshold_entry = DPAA2_ETH_TX_CONG_ENTRY_THRESH; ++ notif_cfg.threshold_exit = DPAA2_ETH_TX_CONG_EXIT_THRESH; ++ notif_cfg.message_ctx = (u64)priv; ++ notif_cfg.message_iova = priv->cscn_dma; ++ notif_cfg.notification_mode = DPNI_CONG_OPT_WRITE_MEM_ON_ENTER | ++ DPNI_CONG_OPT_WRITE_MEM_ON_EXIT | ++ DPNI_CONG_OPT_COHERENT_WRITE; ++ err = dpni_set_congestion_notification(priv->mc_io, 0, ++ priv->mc_token, ++ DPNI_QUEUE_TX, tc_id, ++ ¬if_cfg); ++ if (err) { ++ netdev_err(priv->net_dev, "Error enabling congestion notifications %d\n", ++ err); ++ return err; ++ } ++ break; ++ } ++ ++ /* We can zero out the structure in the tx_prio_conf array */ ++ if (type == DPAA2_ETH_DEL_CQ) { ++ sched_cfg = &sch->prio.tx_prio_cfg.tc_sched[qpri]; ++ memset(sched_cfg, 0, sizeof(*sched_cfg)); ++ } ++ ++ /* Normalize priorities */ ++ err = dpaa2_eth_normalize_tx_prio(sch); ++ ++ /* Debug print goes here */ ++ print_hex_dump_debug("tx_prio: ", DUMP_PREFIX_OFFSET, 16, 1, ++ &sch->prio.tx_prio_cfg, ++ sizeof(sch->prio.tx_prio_cfg), 0); ++ ++ /* Call dpni_set_tx_priorities for the entire prio qdisc */ ++ err = dpni_set_tx_priorities(priv->mc_io, 0, priv->mc_token, ++ &sch->prio.tx_prio_cfg); ++ if (err) ++ netdev_err(priv->net_dev, "dpni_set_tx_priorities err %d\n", ++ err); ++ ++ return err; ++} ++ ++static void dpaa2_eth_ceetm_enable(struct dpaa2_eth_priv *priv) ++{ ++ priv->ceetm_en = true; ++} ++ ++static void dpaa2_eth_ceetm_disable(struct dpaa2_eth_priv *priv) ++{ ++ priv->ceetm_en = false; ++} ++ ++/* Find class in qdisc hash table using given handle */ ++static inline struct dpaa2_ceetm_class *dpaa2_ceetm_find(u32 handle, ++ struct Qdisc *sch) ++{ ++ struct dpaa2_ceetm_qdisc *priv = qdisc_priv(sch); ++ struct Qdisc_class_common *clc; ++ ++ pr_debug(KBUILD_BASENAME " : %s : find class %X in qdisc %X\n", ++ __func__, handle, sch->handle); ++ ++ clc = qdisc_class_find(&priv->clhash, handle); ++ return clc ? container_of(clc, struct dpaa2_ceetm_class, common) : NULL; ++} ++ ++/* Insert a class in the qdisc's class hash */ ++static void dpaa2_ceetm_link_class(struct Qdisc *sch, ++ struct Qdisc_class_hash *clhash, ++ struct Qdisc_class_common *common) ++{ ++ sch_tree_lock(sch); ++ qdisc_class_hash_insert(clhash, common); ++ sch_tree_unlock(sch); ++ qdisc_class_hash_grow(sch, clhash); ++} ++ ++/* Destroy a ceetm class */ ++static void dpaa2_ceetm_cls_destroy(struct Qdisc *sch, ++ struct dpaa2_ceetm_class *cl) ++{ ++ struct net_device *dev = qdisc_dev(sch); ++ struct dpaa2_eth_priv *priv = netdev_priv(dev); ++ ++ if (!cl) ++ return; ++ ++ pr_debug(KBUILD_BASENAME " : %s : destroy class %X from under %X\n", ++ __func__, cl->common.classid, sch->handle); ++ ++ /* Recurse into child first */ ++ if (cl->child) { ++ qdisc_destroy(cl->child); ++ cl->child = NULL; ++ } ++ ++ switch (cl->type) { ++ case CEETM_ROOT: ++ if (dpaa2_eth_reset_ch_shaping(priv, cl->root.ch_id)) ++ netdev_err(dev, "Error resetting channel shaping\n"); ++ ++ break; ++ ++ case CEETM_PRIO: ++ if (dpaa2_eth_update_tx_prio(priv, cl, DPAA2_ETH_DEL_CQ)) ++ netdev_err(dev, "Error resetting tx_priorities\n"); ++ ++ if (cl->prio.cstats) ++ free_percpu(cl->prio.cstats); ++ ++ break; ++ } ++ ++ tcf_destroy_chain(&cl->filter_list); ++ kfree(cl); ++} ++ ++/* Destroy a ceetm qdisc */ ++static void dpaa2_ceetm_destroy(struct Qdisc *sch) ++{ ++ unsigned int i; ++ struct hlist_node *next; ++ struct dpaa2_ceetm_class *cl; ++ struct dpaa2_ceetm_qdisc *priv = qdisc_priv(sch); ++ struct net_device *dev = qdisc_dev(sch); ++ struct dpaa2_eth_priv *priv_eth = netdev_priv(dev); ++ ++ pr_debug(KBUILD_BASENAME " : %s : destroy qdisc %X\n", ++ __func__, sch->handle); ++ ++ /* All filters need to be removed before destroying the classes */ ++ tcf_destroy_chain(&priv->filter_list); ++ ++ for (i = 0; i < priv->clhash.hashsize; i++) { ++ hlist_for_each_entry(cl, &priv->clhash.hash[i], common.hnode) ++ tcf_destroy_chain(&cl->filter_list); ++ } ++ ++ for (i = 0; i < priv->clhash.hashsize; i++) { ++ hlist_for_each_entry_safe(cl, next, &priv->clhash.hash[i], ++ common.hnode) ++ dpaa2_ceetm_cls_destroy(sch, cl); ++ } ++ ++ qdisc_class_hash_destroy(&priv->clhash); ++ ++ switch (priv->type) { ++ case CEETM_ROOT: ++ dpaa2_eth_ceetm_disable(priv_eth); ++ ++ if (priv->root.qstats) ++ free_percpu(priv->root.qstats); ++ ++ if (!priv->root.qdiscs) ++ break; ++ ++ /* Destroy the pfifo qdiscs in case they haven't been attached ++ * to the netdev queues yet. ++ */ ++ for (i = 0; i < dev->num_tx_queues; i++) ++ if (priv->root.qdiscs[i]) ++ qdisc_destroy(priv->root.qdiscs[i]); ++ ++ kfree(priv->root.qdiscs); ++ break; ++ ++ case CEETM_PRIO: ++ if (priv->prio.parent) ++ priv->prio.parent->child = NULL; ++ break; ++ } ++} ++ ++static int dpaa2_ceetm_dump(struct Qdisc *sch, struct sk_buff *skb) ++{ ++ struct Qdisc *qdisc; ++ unsigned int ntx, i; ++ struct nlattr *nest; ++ struct dpaa2_ceetm_tc_qopt qopt; ++ struct dpaa2_ceetm_qdisc_stats *qstats; ++ struct net_device *dev = qdisc_dev(sch); ++ struct dpaa2_ceetm_qdisc *priv = qdisc_priv(sch); ++ ++ pr_debug(KBUILD_BASENAME " : %s : qdisc %X\n", __func__, sch->handle); ++ ++ sch_tree_lock(sch); ++ memset(&qopt, 0, sizeof(qopt)); ++ qopt.type = priv->type; ++ qopt.shaped = priv->shaped; ++ ++ switch (priv->type) { ++ case CEETM_ROOT: ++ /* Gather statistics from the underlying pfifo qdiscs */ ++ sch->q.qlen = 0; ++ memset(&sch->bstats, 0, sizeof(sch->bstats)); ++ memset(&sch->qstats, 0, sizeof(sch->qstats)); ++ ++ for (ntx = 0; ntx < dev->num_tx_queues; ntx++) { ++ qdisc = netdev_get_tx_queue(dev, ntx)->qdisc_sleeping; ++ sch->q.qlen += qdisc->q.qlen; ++ sch->bstats.bytes += qdisc->bstats.bytes; ++ sch->bstats.packets += qdisc->bstats.packets; ++ sch->qstats.qlen += qdisc->qstats.qlen; ++ sch->qstats.backlog += qdisc->qstats.backlog; ++ sch->qstats.drops += qdisc->qstats.drops; ++ sch->qstats.requeues += qdisc->qstats.requeues; ++ sch->qstats.overlimits += qdisc->qstats.overlimits; ++ } ++ ++ for_each_online_cpu(i) { ++ qstats = per_cpu_ptr(priv->root.qstats, i); ++ sch->qstats.drops += qstats->drops; ++ } ++ ++ break; ++ ++ case CEETM_PRIO: ++ qopt.prio_group_A = priv->prio.tx_prio_cfg.prio_group_A; ++ qopt.prio_group_B = priv->prio.tx_prio_cfg.prio_group_B; ++ qopt.separate_groups = priv->prio.tx_prio_cfg.separate_groups; ++ break; ++ ++ default: ++ pr_err(KBUILD_BASENAME " : %s : invalid qdisc\n", __func__); ++ sch_tree_unlock(sch); ++ return -EINVAL; ++ } ++ ++ nest = nla_nest_start(skb, TCA_OPTIONS); ++ if (!nest) ++ goto nla_put_failure; ++ if (nla_put(skb, DPAA2_CEETM_TCA_QOPS, sizeof(qopt), &qopt)) ++ goto nla_put_failure; ++ nla_nest_end(skb, nest); ++ ++ sch_tree_unlock(sch); ++ return skb->len; ++ ++nla_put_failure: ++ sch_tree_unlock(sch); ++ nla_nest_cancel(skb, nest); ++ return -EMSGSIZE; ++} ++ ++static int dpaa2_ceetm_change_prio(struct Qdisc *sch, ++ struct dpaa2_ceetm_qdisc *priv, ++ struct dpaa2_ceetm_tc_qopt *qopt) ++{ ++ /* TODO: Once LX2 support is added */ ++ /* priv->shaped = parent_cl->shaped; */ ++ priv->prio.tx_prio_cfg.prio_group_A = qopt->prio_group_A; ++ priv->prio.tx_prio_cfg.prio_group_B = qopt->prio_group_B; ++ priv->prio.tx_prio_cfg.separate_groups = qopt->separate_groups; ++ ++ return 0; ++} ++ ++/* Edit a ceetm qdisc */ ++static int dpaa2_ceetm_change(struct Qdisc *sch, struct nlattr *opt) ++{ ++ struct dpaa2_ceetm_qdisc *priv = qdisc_priv(sch); ++ struct nlattr *tb[DPAA2_CEETM_TCA_QOPS + 1]; ++ struct dpaa2_ceetm_tc_qopt *qopt; ++ int err; ++ ++ pr_debug(KBUILD_BASENAME " : %s : qdisc %X\n", __func__, sch->handle); ++ ++ err = nla_parse_nested(tb, DPAA2_CEETM_TCA_QOPS, opt, ++ dpaa2_ceetm_policy); ++ if (err < 0) { ++ pr_err(KBUILD_BASENAME " : %s : tc error in %s\n", __func__, ++ "nla_parse_nested"); ++ return err; ++ } ++ ++ if (!tb[DPAA2_CEETM_TCA_QOPS]) { ++ pr_err(KBUILD_BASENAME " : %s : tc error in %s\n", __func__, ++ "tb"); ++ return -EINVAL; ++ } ++ ++ if (TC_H_MIN(sch->handle)) { ++ pr_err("CEETM: a qdisc should not have a minor\n"); ++ return -EINVAL; ++ } ++ ++ qopt = nla_data(tb[DPAA2_CEETM_TCA_QOPS]); ++ ++ if (priv->type != qopt->type) { ++ pr_err("CEETM: qdisc %X is not of the provided type\n", ++ sch->handle); ++ return -EINVAL; ++ } ++ ++ switch (priv->type) { ++ case CEETM_PRIO: ++ err = dpaa2_ceetm_change_prio(sch, priv, qopt); ++ break; ++ default: ++ pr_err(KBUILD_BASENAME " : %s : invalid qdisc\n", __func__); ++ err = -EINVAL; ++ } ++ ++ return err; ++} ++ ++/* Configure a root ceetm qdisc */ ++static int dpaa2_ceetm_init_root(struct Qdisc *sch, ++ struct dpaa2_ceetm_qdisc *priv, ++ struct dpaa2_ceetm_tc_qopt *qopt) ++{ ++ struct net_device *dev = qdisc_dev(sch); ++ struct dpaa2_eth_priv *priv_eth = netdev_priv(dev); ++ struct netdev_queue *dev_queue; ++ unsigned int i, parent_id; ++ struct Qdisc *qdisc; ++ int err; ++ ++ pr_debug(KBUILD_BASENAME " : %s : qdisc %X\n", __func__, sch->handle); ++ ++ /* Validate inputs */ ++ if (sch->parent != TC_H_ROOT) { ++ pr_err("CEETM: a root ceetm qdisc can not be attached to a class\n"); ++ tcf_destroy_chain(&priv->filter_list); ++ qdisc_class_hash_destroy(&priv->clhash); ++ return -EINVAL; ++ } ++ ++ /* Pre-allocate underlying pfifo qdiscs. ++ * ++ * We want to offload shaping and scheduling decisions to the hardware. ++ * The pfifo qdiscs will be attached to the netdev queues and will ++ * guide the traffic from the IP stack down to the driver with minimum ++ * interference. ++ * ++ * The CEETM qdiscs and classes will be crossed when the traffic ++ * reaches the driver. ++ */ ++ priv->root.qdiscs = kcalloc(dev->num_tx_queues, ++ sizeof(priv->root.qdiscs[0]), ++ GFP_KERNEL); ++ if (!priv->root.qdiscs) { ++ err = -ENOMEM; ++ goto err_init_root; ++ } ++ ++ for (i = 0; i < dev->num_tx_queues; i++) { ++ dev_queue = netdev_get_tx_queue(dev, i); ++ parent_id = TC_H_MAKE(TC_H_MAJ(sch->handle), ++ TC_H_MIN(i + PFIFO_MIN_OFFSET)); ++ ++ qdisc = qdisc_create_dflt(dev_queue, &pfifo_qdisc_ops, ++ parent_id); ++ if (!qdisc) { ++ err = -ENOMEM; ++ goto err_init_root; ++ } ++ ++ priv->root.qdiscs[i] = qdisc; ++ qdisc->flags |= TCQ_F_ONETXQUEUE; ++ } ++ ++ sch->flags |= TCQ_F_MQROOT; ++ ++ priv->root.qstats = alloc_percpu(struct dpaa2_ceetm_qdisc_stats); ++ if (!priv->root.qstats) { ++ pr_err(KBUILD_BASENAME " : %s : alloc_percpu() failed\n", ++ __func__); ++ err = -ENOMEM; ++ goto err_init_root; ++ } ++ ++ dpaa2_eth_ceetm_enable(priv_eth); ++ return 0; ++ ++err_init_root: ++ dpaa2_ceetm_destroy(sch); ++ return err; ++} ++ ++/* Configure a prio ceetm qdisc */ ++static int dpaa2_ceetm_init_prio(struct Qdisc *sch, ++ struct dpaa2_ceetm_qdisc *priv, ++ struct dpaa2_ceetm_tc_qopt *qopt) ++{ ++ struct net_device *dev = qdisc_dev(sch); ++ struct dpaa2_ceetm_class *parent_cl; ++ struct Qdisc *parent_qdisc; ++ int err; ++ ++ pr_debug(KBUILD_BASENAME " : %s : qdisc %X\n", __func__, sch->handle); ++ ++ if (sch->parent == TC_H_ROOT) { ++ pr_err("CEETM: a prio ceetm qdisc can not be root\n"); ++ err = -EINVAL; ++ goto err_init_prio; ++ } ++ ++ parent_qdisc = qdisc_lookup(dev, TC_H_MAJ(sch->parent)); ++ if (strcmp(parent_qdisc->ops->id, dpaa2_ceetm_qdisc_ops.id)) { ++ pr_err("CEETM: a ceetm qdisc can not be attached to other qdisc/class types\n"); ++ err = -EINVAL; ++ goto err_init_prio; ++ } ++ ++ /* Obtain the parent root ceetm_class */ ++ parent_cl = dpaa2_ceetm_find(sch->parent, parent_qdisc); ++ ++ if (!parent_cl || parent_cl->type != CEETM_ROOT) { ++ pr_err("CEETM: a prio ceetm qdiscs can be added only under a root ceetm class\n"); ++ err = -EINVAL; ++ goto err_init_prio; ++ } ++ ++ priv->prio.parent = parent_cl; ++ parent_cl->child = sch; ++ ++ err = dpaa2_ceetm_change_prio(sch, priv, qopt); ++ ++ return 0; ++ ++err_init_prio: ++ dpaa2_ceetm_destroy(sch); ++ return err; ++} ++ ++/* Configure a generic ceetm qdisc */ ++static int dpaa2_ceetm_init(struct Qdisc *sch, struct nlattr *opt) ++{ ++ struct dpaa2_ceetm_qdisc *priv = qdisc_priv(sch); ++ struct net_device *dev = qdisc_dev(sch); ++ struct nlattr *tb[DPAA2_CEETM_TCA_QOPS + 1]; ++ struct dpaa2_ceetm_tc_qopt *qopt; ++ int err; ++ ++ pr_debug(KBUILD_BASENAME " : %s : qdisc %X\n", __func__, sch->handle); ++ ++ if (!netif_is_multiqueue(dev)) ++ return -EOPNOTSUPP; ++ ++ RCU_INIT_POINTER(priv->filter_list, NULL); ++ ++ if (!opt) { ++ pr_err(KBUILD_BASENAME " : %s : tc error - opt = NULL\n", ++ __func__); ++ return -EINVAL; ++ } ++ ++ err = nla_parse_nested(tb, DPAA2_CEETM_TCA_QOPS, opt, ++ dpaa2_ceetm_policy); ++ if (err < 0) { ++ pr_err(KBUILD_BASENAME " : %s : tc error in %s\n", __func__, ++ "nla_parse_nested"); ++ return err; ++ } ++ ++ if (!tb[DPAA2_CEETM_TCA_QOPS]) { ++ pr_err(KBUILD_BASENAME " : %s : tc error in %s\n", __func__, ++ "tb"); ++ return -EINVAL; ++ } ++ ++ if (TC_H_MIN(sch->handle)) { ++ pr_err("CEETM: a qdisc should not have a minor\n"); ++ return -EINVAL; ++ } ++ ++ qopt = nla_data(tb[DPAA2_CEETM_TCA_QOPS]); ++ ++ /* Initialize the class hash list. Each qdisc has its own class hash */ ++ err = qdisc_class_hash_init(&priv->clhash); ++ if (err < 0) { ++ pr_err(KBUILD_BASENAME " : %s : qdisc_class_hash_init failed\n", ++ __func__); ++ return err; ++ } ++ ++ priv->type = qopt->type; ++ priv->shaped = qopt->shaped; ++ ++ switch (priv->type) { ++ case CEETM_ROOT: ++ err = dpaa2_ceetm_init_root(sch, priv, qopt); ++ break; ++ case CEETM_PRIO: ++ err = dpaa2_ceetm_init_prio(sch, priv, qopt); ++ break; ++ default: ++ pr_err(KBUILD_BASENAME " : %s : invalid qdisc\n", __func__); ++ dpaa2_ceetm_destroy(sch); ++ err = -EINVAL; ++ } ++ ++ return err; ++} ++ ++/* Attach the underlying pfifo qdiscs */ ++static void dpaa2_ceetm_attach(struct Qdisc *sch) ++{ ++ struct net_device *dev = qdisc_dev(sch); ++ struct dpaa2_ceetm_qdisc *priv = qdisc_priv(sch); ++ struct Qdisc *qdisc, *old_qdisc; ++ unsigned int i; ++ ++ pr_debug(KBUILD_BASENAME " : %s : qdisc %X\n", __func__, sch->handle); ++ ++ for (i = 0; i < dev->num_tx_queues; i++) { ++ qdisc = priv->root.qdiscs[i]; ++ old_qdisc = dev_graft_qdisc(qdisc->dev_queue, qdisc); ++ if (old_qdisc) ++ qdisc_destroy(old_qdisc); ++ } ++ ++ /* Remove the references to the pfifo qdiscs since the kernel will ++ * destroy them when needed. No cleanup from our part is required from ++ * this point on. ++ */ ++ kfree(priv->root.qdiscs); ++ priv->root.qdiscs = NULL; ++} ++ ++static unsigned long dpaa2_ceetm_cls_get(struct Qdisc *sch, u32 classid) ++{ ++ struct dpaa2_ceetm_class *cl; ++ ++ pr_debug(KBUILD_BASENAME " : %s : classid %X from qdisc %X\n", ++ __func__, classid, sch->handle); ++ cl = dpaa2_ceetm_find(classid, sch); ++ ++ if (cl) ++ cl->refcnt++; ++ ++ return (unsigned long)cl; ++} ++ ++static void dpaa2_ceetm_cls_put(struct Qdisc *sch, unsigned long arg) ++{ ++ struct dpaa2_ceetm_class *cl = (struct dpaa2_ceetm_class *)arg; ++ pr_debug(KBUILD_BASENAME " : %s : classid %X from qdisc %X\n", ++ __func__, cl->common.classid, sch->handle); ++ cl->refcnt--; ++ ++ if (cl->refcnt == 0) ++ dpaa2_ceetm_cls_destroy(sch, cl); ++} ++ ++static int dpaa2_ceetm_cls_change_root(struct dpaa2_ceetm_class *cl, ++ struct dpaa2_ceetm_tc_copt *copt, ++ struct net_device *dev) ++{ ++ struct dpaa2_eth_priv *priv = netdev_priv(dev); ++ struct dpni_tx_shaping_cfg scfg = { 0 }, ecfg = { 0 }; ++ int err = 0; ++ ++ pr_debug(KBUILD_BASENAME " : %s : class %X\n", __func__, ++ cl->common.classid); ++ ++ if (!cl->shaped) ++ return 0; ++ ++ if (dpaa2_eth_update_shaping_cfg(dev, copt->shaping_cfg, ++ &scfg, &ecfg)) ++ return -EINVAL; ++ ++ err = dpaa2_eth_set_ch_shaping(priv, &scfg, &ecfg, ++ copt->shaping_cfg.coupled, ++ cl->root.ch_id); ++ if (err) ++ return err; ++ ++ memcpy(&cl->root.shaping_cfg, &copt->shaping_cfg, ++ sizeof(struct dpaa2_ceetm_shaping_cfg)); ++ ++ return err; ++} ++ ++static int dpaa2_ceetm_cls_change_prio(struct dpaa2_ceetm_class *cl, ++ struct dpaa2_ceetm_tc_copt *copt, ++ struct net_device *dev) ++{ ++ struct dpaa2_ceetm_qdisc *sch = qdisc_priv(cl->parent); ++ struct dpni_tx_schedule_cfg *sched_cfg; ++ struct dpaa2_eth_priv *priv = netdev_priv(dev); ++ int err; ++ ++ pr_debug(KBUILD_BASENAME " : %s : class %X mode %d weight %d\n", ++ __func__, cl->common.classid, copt->mode, copt->weight); ++ ++ if (!cl->prio.cstats) { ++ cl->prio.cstats = alloc_percpu(struct dpaa2_ceetm_class_stats); ++ if (!cl->prio.cstats) { ++ pr_err(KBUILD_BASENAME " : %s : alloc_percpu() failed\n", ++ __func__); ++ return -ENOMEM; ++ } ++ } ++ ++ cl->prio.mode = copt->mode; ++ cl->prio.weight = copt->weight; ++ ++ sched_cfg = &sch->prio.tx_prio_cfg.tc_sched[cl->prio.qpri]; ++ ++ switch (copt->mode) { ++ case STRICT_PRIORITY: ++ sched_cfg->mode = DPNI_TX_SCHED_STRICT_PRIORITY; ++ break; ++ case WEIGHTED_A: ++ sched_cfg->mode = DPNI_TX_SCHED_WEIGHTED_A; ++ break; ++ case WEIGHTED_B: ++ sched_cfg->mode = DPNI_TX_SCHED_WEIGHTED_B; ++ break; ++ } ++ ++ err = dpaa2_eth_update_tx_prio(priv, cl, DPAA2_ETH_ADD_CQ); ++ ++ return err; ++} ++ ++/* Add a new ceetm class */ ++static int dpaa2_ceetm_cls_add(struct Qdisc *sch, u32 classid, ++ struct dpaa2_ceetm_tc_copt *copt, ++ unsigned long *arg) ++{ ++ struct dpaa2_ceetm_qdisc *priv = qdisc_priv(sch); ++ struct net_device *dev = qdisc_dev(sch); ++ struct dpaa2_eth_priv *priv_eth = netdev_priv(dev); ++ struct dpaa2_ceetm_class *cl; ++ int err; ++ ++ if (copt->type == CEETM_ROOT && ++ priv->clhash.hashelems == dpaa2_eth_ch_count(priv_eth)) { ++ pr_err("CEETM: only %d channel%s per DPNI allowed, sorry\n", ++ dpaa2_eth_ch_count(priv_eth), ++ dpaa2_eth_ch_count(priv_eth) == 1 ? "" : "s"); ++ return -EINVAL; ++ } ++ ++ if (copt->type == CEETM_PRIO && ++ priv->clhash.hashelems == dpaa2_eth_tc_count(priv_eth)) { ++ pr_err("CEETM: only %d queue%s per channel allowed, sorry\n", ++ dpaa2_eth_tc_count(priv_eth), ++ dpaa2_eth_tc_count(priv_eth) == 1 ? "" : "s"); ++ return -EINVAL; ++ } ++ ++ cl = kzalloc(sizeof(*cl), GFP_KERNEL); ++ if (!cl) ++ return -ENOMEM; ++ ++ RCU_INIT_POINTER(cl->filter_list, NULL); ++ ++ cl->common.classid = classid; ++ cl->refcnt = 1; ++ cl->parent = sch; ++ cl->child = NULL; ++ ++ /* Add class handle in Qdisc */ ++ dpaa2_ceetm_link_class(sch, &priv->clhash, &cl->common); ++ ++ cl->shaped = copt->shaped; ++ cl->type = copt->type; ++ ++ /* Claim a CEETM channel / tc - DPAA2. will assume transition from ++ * classid to qdid/qpri, starting from qdid / qpri 0 ++ */ ++ switch (copt->type) { ++ case CEETM_ROOT: ++ cl->root.ch_id = classid - sch->handle - 1; ++ err = dpaa2_ceetm_cls_change_root(cl, copt, dev); ++ break; ++ case CEETM_PRIO: ++ cl->prio.qpri = classid - sch->handle - 1; ++ err = dpaa2_ceetm_cls_change_prio(cl, copt, dev); ++ break; ++ default: ++ err = -EINVAL; ++ break; ++ } ++ ++ if (err) { ++ pr_err("%s: Unable to set new %s class\n", __func__, ++ (copt->type == CEETM_ROOT ? "root" : "prio")); ++ goto out_free; ++ } ++ ++ switch (copt->type) { ++ case CEETM_ROOT: ++ pr_debug(KBUILD_BASENAME " : %s : configured root class %X associated with channel qdid %d\n", ++ __func__, classid, cl->root.ch_id); ++ break; ++ case CEETM_PRIO: ++ pr_debug(KBUILD_BASENAME " : %s : configured prio class %X associated with queue qpri %d\n", ++ __func__, classid, cl->prio.qpri); ++ break; ++ } ++ ++ *arg = (unsigned long)cl; ++ return 0; ++ ++out_free: ++ kfree(cl); ++ return err; ++} ++ ++/* Add or configure a ceetm class */ ++static int dpaa2_ceetm_cls_change(struct Qdisc *sch, u32 classid, u32 parentid, ++ struct nlattr **tca, unsigned long *arg) ++{ ++ struct dpaa2_ceetm_qdisc *priv; ++ struct dpaa2_ceetm_class *cl = (struct dpaa2_ceetm_class *)*arg; ++ struct nlattr *opt = tca[TCA_OPTIONS]; ++ struct nlattr *tb[DPAA2_CEETM_TCA_MAX]; ++ struct dpaa2_ceetm_tc_copt *copt; ++ struct net_device *dev = qdisc_dev(sch); ++ int err; ++ ++ pr_debug(KBUILD_BASENAME " : %s : classid %X under qdisc %X\n", ++ __func__, classid, sch->handle); ++ ++ if (strcmp(sch->ops->id, dpaa2_ceetm_qdisc_ops.id)) { ++ pr_err("CEETM: a ceetm class can not be attached to other qdisc/class types\n"); ++ return -EINVAL; ++ } ++ ++ priv = qdisc_priv(sch); ++ ++ if (!opt) { ++ pr_err(KBUILD_BASENAME " : %s : tc error NULL opt\n", __func__); ++ return -EINVAL; ++ } ++ ++ err = nla_parse_nested(tb, DPAA2_CEETM_TCA_COPT, opt, ++ dpaa2_ceetm_policy); ++ if (err < 0) { ++ pr_err(KBUILD_BASENAME " : %s : tc error in %s\n", __func__, ++ "nla_parse_nested"); ++ return -EINVAL; ++ } ++ ++ if (!tb[DPAA2_CEETM_TCA_COPT]) { ++ pr_err(KBUILD_BASENAME " : %s : tc error in %s\n", __func__, ++ "tb"); ++ return -EINVAL; ++ } ++ ++ copt = nla_data(tb[DPAA2_CEETM_TCA_COPT]); ++ ++ /* Configure an existing ceetm class */ ++ if (cl) { ++ if (copt->type != cl->type) { ++ pr_err("CEETM: class %X is not of the provided type\n", ++ cl->common.classid); ++ return -EINVAL; ++ } ++ ++ switch (copt->type) { ++ case CEETM_ROOT: ++ return dpaa2_ceetm_cls_change_root(cl, copt, dev); ++ case CEETM_PRIO: ++ return dpaa2_ceetm_cls_change_prio(cl, copt, dev); ++ ++ default: ++ pr_err(KBUILD_BASENAME " : %s : invalid class\n", ++ __func__); ++ return -EINVAL; ++ } ++ } ++ ++ return dpaa2_ceetm_cls_add(sch, classid, copt, arg); ++} ++ ++static void dpaa2_ceetm_cls_walk(struct Qdisc *sch, struct qdisc_walker *arg) ++{ ++ struct dpaa2_ceetm_qdisc *priv = qdisc_priv(sch); ++ struct dpaa2_ceetm_class *cl; ++ unsigned int i; ++ ++ pr_debug(KBUILD_BASENAME " : %s : qdisc %X\n", __func__, sch->handle); ++ ++ if (arg->stop) ++ return; ++ ++ for (i = 0; i < priv->clhash.hashsize; i++) { ++ hlist_for_each_entry(cl, &priv->clhash.hash[i], common.hnode) { ++ if (arg->count < arg->skip) { ++ arg->count++; ++ continue; ++ } ++ if (arg->fn(sch, (unsigned long)cl, arg) < 0) { ++ arg->stop = 1; ++ return; ++ } ++ arg->count++; ++ } ++ } ++} ++ ++static int dpaa2_ceetm_cls_dump(struct Qdisc *sch, unsigned long arg, ++ struct sk_buff *skb, struct tcmsg *tcm) ++{ ++ struct dpaa2_ceetm_class *cl = (struct dpaa2_ceetm_class *)arg; ++ struct nlattr *nest; ++ struct dpaa2_ceetm_tc_copt copt; ++ ++ pr_debug(KBUILD_BASENAME " : %s : class %X under qdisc %X\n", ++ __func__, cl->common.classid, sch->handle); ++ ++ sch_tree_lock(sch); ++ ++ tcm->tcm_parent = ((struct Qdisc *)cl->parent)->handle; ++ tcm->tcm_handle = cl->common.classid; ++ ++ memset(&copt, 0, sizeof(copt)); ++ ++ copt.shaped = cl->shaped; ++ copt.type = cl->type; ++ ++ switch (cl->type) { ++ case CEETM_ROOT: ++ if (cl->child) ++ tcm->tcm_info = cl->child->handle; ++ ++ memcpy(&copt.shaping_cfg, &cl->root.shaping_cfg, ++ sizeof(struct dpaa2_ceetm_shaping_cfg)); ++ ++ break; ++ ++ case CEETM_PRIO: ++ if (cl->child) ++ tcm->tcm_info = cl->child->handle; ++ ++ copt.mode = cl->prio.mode; ++ copt.weight = cl->prio.weight; ++ ++ break; ++ } ++ ++ nest = nla_nest_start(skb, TCA_OPTIONS); ++ if (!nest) ++ goto nla_put_failure; ++ if (nla_put(skb, DPAA2_CEETM_TCA_COPT, sizeof(copt), &copt)) ++ goto nla_put_failure; ++ nla_nest_end(skb, nest); ++ sch_tree_unlock(sch); ++ return skb->len; ++ ++nla_put_failure: ++ sch_tree_unlock(sch); ++ nla_nest_cancel(skb, nest); ++ return -EMSGSIZE; ++} ++ ++static int dpaa2_ceetm_cls_delete(struct Qdisc *sch, unsigned long arg) ++{ ++ struct dpaa2_ceetm_qdisc *priv = qdisc_priv(sch); ++ struct dpaa2_ceetm_class *cl = (struct dpaa2_ceetm_class *)arg; ++ ++ pr_debug(KBUILD_BASENAME " : %s : class %X under qdisc %X\n", ++ __func__, cl->common.classid, sch->handle); ++ ++ sch_tree_lock(sch); ++ qdisc_class_hash_remove(&priv->clhash, &cl->common); ++ cl->refcnt--; ++ WARN_ON(cl->refcnt == 0); ++ sch_tree_unlock(sch); ++ return 0; ++} ++ ++/* Get the class' child qdisc, if any */ ++static struct Qdisc *dpaa2_ceetm_cls_leaf(struct Qdisc *sch, unsigned long arg) ++{ ++ struct dpaa2_ceetm_class *cl = (struct dpaa2_ceetm_class *)arg; ++ ++ pr_debug(KBUILD_BASENAME " : %s : class %X under qdisc %X\n", ++ __func__, cl->common.classid, sch->handle); ++ ++ switch (cl->type) { ++ case CEETM_ROOT: ++ case CEETM_PRIO: ++ return cl->child; ++ } ++ ++ return NULL; ++} ++ ++static int dpaa2_ceetm_cls_graft(struct Qdisc *sch, unsigned long arg, ++ struct Qdisc *new, struct Qdisc **old) ++{ ++ if (new && strcmp(new->ops->id, dpaa2_ceetm_qdisc_ops.id)) { ++ pr_err("CEETM: only ceetm qdiscs can be attached to ceetm classes\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ return 0; ++} ++ ++static int dpaa2_ceetm_cls_dump_stats(struct Qdisc *sch, unsigned long arg, ++ struct gnet_dump *d) ++{ ++ struct dpaa2_ceetm_class *cl = (struct dpaa2_ceetm_class *)arg; ++ struct gnet_stats_basic_packed tmp_bstats; ++ struct dpaa2_ceetm_tc_xstats xstats; ++ union dpni_statistics dpni_stats; ++ struct net_device *dev = qdisc_dev(sch); ++ struct dpaa2_eth_priv *priv_eth = netdev_priv(dev); ++ u8 ch_id = 0; ++ int err; ++ ++ memset(&xstats, 0, sizeof(xstats)); ++ memset(&tmp_bstats, 0, sizeof(tmp_bstats)); ++ ++ if (cl->type == CEETM_ROOT) ++ return 0; ++ ++ err = dpni_get_statistics(priv_eth->mc_io, 0, priv_eth->mc_token, 3, ++ DPNI_BUILD_CH_TC(ch_id, cl->prio.qpri), ++ &dpni_stats); ++ if (err) ++ netdev_warn(dev, "dpni_get_stats(%d) failed - %d\n", 3, err); ++ ++ xstats.ceetm_dequeue_bytes = dpni_stats.page_3.ceetm_dequeue_bytes; ++ xstats.ceetm_dequeue_frames = dpni_stats.page_3.ceetm_dequeue_frames; ++ xstats.ceetm_reject_bytes = dpni_stats.page_3.ceetm_reject_bytes; ++ xstats.ceetm_reject_frames = dpni_stats.page_3.ceetm_reject_frames; ++ ++ return gnet_stats_copy_app(d, &xstats, sizeof(xstats)); ++} ++ ++static struct tcf_proto __rcu **dpaa2_ceetm_tcf_chain(struct Qdisc *sch, ++ unsigned long arg) ++{ ++ struct dpaa2_ceetm_qdisc *priv = qdisc_priv(sch); ++ struct dpaa2_ceetm_class *cl = (struct dpaa2_ceetm_class *)arg; ++ ++ pr_debug(KBUILD_BASENAME " : %s : class %X under qdisc %X\n", __func__, ++ cl ? cl->common.classid : 0, sch->handle); ++ return cl ? &cl->filter_list : &priv->filter_list; ++} ++ ++static unsigned long dpaa2_ceetm_tcf_bind(struct Qdisc *sch, ++ unsigned long parent, ++ u32 classid) ++{ ++ struct dpaa2_ceetm_class *cl = dpaa2_ceetm_find(classid, sch); ++ ++ pr_debug(KBUILD_BASENAME " : %s : class %X under qdisc %X\n", __func__, ++ cl ? cl->common.classid : 0, sch->handle); ++ return (unsigned long)cl; ++} ++ ++static void dpaa2_ceetm_tcf_unbind(struct Qdisc *sch, unsigned long arg) ++{ ++ struct dpaa2_ceetm_class *cl = (struct dpaa2_ceetm_class *)arg; ++ ++ pr_debug(KBUILD_BASENAME " : %s : class %X under qdisc %X\n", __func__, ++ cl ? cl->common.classid : 0, sch->handle); ++} ++ ++const struct Qdisc_class_ops dpaa2_ceetm_cls_ops = { ++ .graft = dpaa2_ceetm_cls_graft, ++ .leaf = dpaa2_ceetm_cls_leaf, ++ .get = dpaa2_ceetm_cls_get, ++ .put = dpaa2_ceetm_cls_put, ++ .change = dpaa2_ceetm_cls_change, ++ .delete = dpaa2_ceetm_cls_delete, ++ .walk = dpaa2_ceetm_cls_walk, ++ .tcf_chain = dpaa2_ceetm_tcf_chain, ++ .bind_tcf = dpaa2_ceetm_tcf_bind, ++ .unbind_tcf = dpaa2_ceetm_tcf_unbind, ++ .dump = dpaa2_ceetm_cls_dump, ++ .dump_stats = dpaa2_ceetm_cls_dump_stats, ++}; ++ ++struct Qdisc_ops dpaa2_ceetm_qdisc_ops __read_mostly = { ++ .id = "ceetm", ++ .priv_size = sizeof(struct dpaa2_ceetm_qdisc), ++ .cl_ops = &dpaa2_ceetm_cls_ops, ++ .init = dpaa2_ceetm_init, ++ .destroy = dpaa2_ceetm_destroy, ++ .change = dpaa2_ceetm_change, ++ .dump = dpaa2_ceetm_dump, ++ .attach = dpaa2_ceetm_attach, ++ .owner = THIS_MODULE, ++}; ++ ++/* Run the filters and classifiers attached to the qdisc on the provided skb */ ++int dpaa2_ceetm_classify(struct sk_buff *skb, struct Qdisc *sch, ++ int *qdid, int *qpri) ++{ ++ struct dpaa2_ceetm_qdisc *priv = qdisc_priv(sch); ++ struct dpaa2_ceetm_class *cl = NULL; ++ struct tcf_result res; ++ struct tcf_proto *tcf; ++ int result; ++ ++ tcf = rcu_dereference_bh(priv->filter_list); ++ while (tcf && (result = tc_classify(skb, tcf, &res, false)) >= 0) { ++#ifdef CONFIG_NET_CLS_ACT ++ switch (result) { ++ case TC_ACT_QUEUED: ++ case TC_ACT_STOLEN: ++ case TC_ACT_SHOT: ++ /* No valid class found due to action */ ++ return -1; ++ } ++#endif ++ cl = (void *)res.class; ++ if (!cl) { ++ /* The filter leads to the qdisc */ ++ if (res.classid == sch->handle) ++ return 0; ++ ++ cl = dpaa2_ceetm_find(res.classid, sch); ++ /* The filter leads to an invalid class */ ++ if (!cl) ++ break; ++ } ++ ++ /* The class might have its own filters attached */ ++ tcf = rcu_dereference_bh(cl->filter_list); ++ } ++ ++ /* No valid class found */ ++ if (!cl) ++ return 0; ++ ++ switch (cl->type) { ++ case CEETM_ROOT: ++ *qdid = cl->root.ch_id; ++ ++ /* The root class does not have a child prio qdisc */ ++ if (!cl->child) ++ return 0; ++ ++ /* Run the prio qdisc classifiers */ ++ return dpaa2_ceetm_classify(skb, cl->child, qdid, qpri); ++ ++ case CEETM_PRIO: ++ *qpri = cl->prio.qpri; ++ break; ++ } ++ ++ return 0; ++} ++ ++int __init dpaa2_ceetm_register(void) ++{ ++ int err = 0; ++ ++ pr_debug(KBUILD_MODNAME ": " DPAA2_CEETM_DESCRIPTION "\n"); ++ ++ err = register_qdisc(&dpaa2_ceetm_qdisc_ops); ++ if (unlikely(err)) ++ pr_err(KBUILD_MODNAME ++ ": %s:%hu:%s(): register_qdisc() = %d\n", ++ KBUILD_BASENAME ".c", __LINE__, __func__, err); ++ ++ return err; ++} ++ ++void __exit dpaa2_ceetm_unregister(void) ++{ ++ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", ++ KBUILD_BASENAME ".c", __func__); ++ ++ unregister_qdisc(&dpaa2_ceetm_qdisc_ops); ++} +--- /dev/null ++++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-ceetm.h +@@ -0,0 +1,182 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright 2017 NXP ++ * ++ */ ++ ++#ifndef __DPAA2_ETH_CEETM_H ++#define __DPAA2_ETH_CEETM_H ++ ++#include <net/pkt_sched.h> ++#include <net/pkt_cls.h> ++#include <net/netlink.h> ++ ++#include "dpaa2-eth.h" ++ ++/* For functional purposes, there are num_tx_queues pfifo qdiscs through which ++ * frames reach the driver. Their handles start from 1:21. Handles 1:1 to 1:20 ++ * are reserved for the maximum 32 CEETM channels (majors and minors are in ++ * hex). ++ */ ++#define PFIFO_MIN_OFFSET 0x21 ++ ++#define DPAA2_CEETM_MIN_WEIGHT 100 ++#define DPAA2_CEETM_MAX_WEIGHT 24800 ++ ++#define DPAA2_CEETM_TD_THRESHOLD 1000 ++ ++enum wbfs_group_type { ++ WBFS_GRP_A, ++ WBFS_GRP_B, ++ WBFS_GRP_LARGE ++}; ++ ++enum { ++ DPAA2_CEETM_TCA_UNSPEC, ++ DPAA2_CEETM_TCA_COPT, ++ DPAA2_CEETM_TCA_QOPS, ++ DPAA2_CEETM_TCA_MAX, ++}; ++ ++/* CEETM configuration types */ ++enum dpaa2_ceetm_type { ++ CEETM_ROOT = 1, ++ CEETM_PRIO, ++}; ++ ++enum { ++ STRICT_PRIORITY = 0, ++ WEIGHTED_A, ++ WEIGHTED_B, ++}; ++ ++struct dpaa2_ceetm_shaping_cfg { ++ __u64 cir; /* committed information rate */ ++ __u64 eir; /* excess information rate */ ++ __u16 cbs; /* committed burst size */ ++ __u16 ebs; /* excess burst size */ ++ __u8 coupled; /* shaper coupling */ ++}; ++ ++extern const struct nla_policy ceetm_policy[DPAA2_CEETM_TCA_MAX]; ++ ++struct dpaa2_ceetm_class; ++struct dpaa2_ceetm_qdisc_stats; ++struct dpaa2_ceetm_class_stats; ++ ++/* corresponds to CEETM shaping at LNI level */ ++struct dpaa2_root_q { ++ struct Qdisc **qdiscs; ++ struct dpaa2_ceetm_qdisc_stats __percpu *qstats; ++}; ++ ++/* corresponds to the number of priorities a channel serves */ ++struct dpaa2_prio_q { ++ struct dpaa2_ceetm_class *parent; ++ struct dpni_tx_priorities_cfg tx_prio_cfg; ++}; ++ ++struct dpaa2_ceetm_qdisc { ++ struct Qdisc_class_hash clhash; ++ struct tcf_proto *filter_list; /* qdisc attached filters */ ++ ++ enum dpaa2_ceetm_type type; /* ROOT/PRIO */ ++ bool shaped; ++ union { ++ struct dpaa2_root_q root; ++ struct dpaa2_prio_q prio; ++ }; ++}; ++ ++/* CEETM Qdisc configuration parameters */ ++struct dpaa2_ceetm_tc_qopt { ++ enum dpaa2_ceetm_type type; ++ __u16 shaped; ++ __u8 prio_group_A; ++ __u8 prio_group_B; ++ __u8 separate_groups; ++}; ++ ++/* root class - corresponds to a channel */ ++struct dpaa2_root_c { ++ struct dpaa2_ceetm_shaping_cfg shaping_cfg; ++ u32 ch_id; ++}; ++ ++/* prio class - corresponds to a strict priority queue (group) */ ++struct dpaa2_prio_c { ++ struct dpaa2_ceetm_class_stats __percpu *cstats; ++ u32 qpri; ++ u8 mode; ++ u16 weight; ++}; ++ ++struct dpaa2_ceetm_class { ++ struct Qdisc_class_common common; ++ int refcnt; ++ struct tcf_proto *filter_list; /* class attached filters */ ++ struct Qdisc *parent; ++ struct Qdisc *child; ++ ++ enum dpaa2_ceetm_type type; /* ROOT/PRIO */ ++ bool shaped; ++ union { ++ struct dpaa2_root_c root; ++ struct dpaa2_prio_c prio; ++ }; ++}; ++ ++/* CEETM Class configuration parameters */ ++struct dpaa2_ceetm_tc_copt { ++ enum dpaa2_ceetm_type type; ++ struct dpaa2_ceetm_shaping_cfg shaping_cfg; ++ __u16 shaped; ++ __u8 mode; ++ __u16 weight; ++}; ++ ++/* CEETM stats */ ++struct dpaa2_ceetm_qdisc_stats { ++ __u32 drops; ++}; ++ ++struct dpaa2_ceetm_class_stats { ++ /* Software counters */ ++ struct gnet_stats_basic_packed bstats; ++ __u32 ern_drop_count; ++ __u32 congested_count; ++}; ++ ++struct dpaa2_ceetm_tc_xstats { ++ __u64 ceetm_dequeue_bytes; ++ __u64 ceetm_dequeue_frames; ++ __u64 ceetm_reject_bytes; ++ __u64 ceetm_reject_frames; ++}; ++ ++#ifdef CONFIG_FSL_DPAA2_ETH_CEETM ++int __init dpaa2_ceetm_register(void); ++void __exit dpaa2_ceetm_unregister(void); ++int dpaa2_ceetm_classify(struct sk_buff *skb, struct Qdisc *sch, ++ int *qdid, int *qpri); ++#else ++static inline int dpaa2_ceetm_register(void) ++{ ++ return 0; ++} ++ ++static inline void dpaa2_ceetm_unregister(void) {} ++ ++static inline int dpaa2_ceetm_classify(struct sk_buff *skb, struct Qdisc *sch, ++ int *qdid, int *qpri) ++{ ++ return 0; ++} ++#endif ++ ++static inline bool dpaa2_eth_ceetm_is_enabled(struct dpaa2_eth_priv *priv) ++{ ++ return priv->ceetm_en; ++} ++ ++#endif +--- /dev/null +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-debugfs.c -@@ -0,0 +1,352 @@ +@@ -0,0 +1,357 @@ + +/* Copyright 2015 Freescale Semiconductor Inc. + * @@ -646,14 +2122,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + int i; + + seq_printf(file, "Per-CPU stats for %s\n", priv->net_dev->name); -+ seq_printf(file, "%s%16s%16s%16s%16s%16s%16s%16s%16s\n", ++ seq_printf(file, "%s%16s%16s%16s%16s%16s%16s%16s%16s%16s\n", + "CPU", "Rx", "Rx Err", "Rx SG", "Tx", "Tx Err", "Tx conf", -+ "Tx SG", "Enq busy"); ++ "Tx SG", "Tx realloc", "Enq busy"); + + for_each_online_cpu(i) { + stats = per_cpu_ptr(priv->percpu_stats, i); + extras = per_cpu_ptr(priv->percpu_extras, i); -+ seq_printf(file, "%3d%16llu%16llu%16llu%16llu%16llu%16llu%16llu%16llu\n", ++ seq_printf(file, "%3d%16llu%16llu%16llu%16llu%16llu%16llu%16llu%16llu%16llu\n", + i, + stats->rx_packets, + stats->rx_errors, @@ -662,6 +2138,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + stats->tx_errors, + extras->tx_conf_frames, + extras->tx_sg_frames, ++ extras->tx_reallocs, + extras->tx_portal_busy); + } + @@ -708,7 +2185,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 fcnt, bcnt; + int i, err; + -+ seq_printf(file, "FQ stats for %s:\n", priv->net_dev->name); ++ seq_printf(file, "non-zero FQ stats for %s:\n", priv->net_dev->name); + seq_printf(file, "%s%16s%16s%16s%16s%16s%16s\n", + "VFQID", "CPU", "Traffic Class", "Type", "Frames", + "Pending frames", "Congestion"); @@ -719,6 +2196,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + if (err) + fcnt = 0; + ++ /* A lot of queues, no use displaying zero traffic ones */ ++ if (!fq->stats.frames && !fcnt) ++ continue; ++ + seq_printf(file, "%5d%16d%16d%16s%16llu%16u%16llu\n", + fq->fqid, + fq->target_cpu, @@ -1014,7 +2495,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#endif /* DPAA2_ETH_DEBUGFS_H */ --- /dev/null +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-trace.h -@@ -0,0 +1,184 @@ +@@ -0,0 +1,185 @@ +/* Copyright 2014-2015 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without @@ -1054,6 +2535,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +#include <linux/skbuff.h> +#include <linux/netdevice.h> ++#include "dpaa2-eth.h" +#include <linux/tracepoint.h> + +#define TR_FMT "[%s] fd: addr=0x%llx, len=%u, off=%u" @@ -1201,8 +2683,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#include <trace/define_trace.h> --- /dev/null +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c -@@ -0,0 +1,3516 @@ -+/* Copyright 2014-2015 Freescale Semiconductor Inc. +@@ -0,0 +1,3734 @@ ++/* Copyright 2014-2016 Freescale Semiconductor Inc. ++ * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: @@ -1238,18 +2721,17 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#include <linux/etherdevice.h> +#include <linux/of_net.h> +#include <linux/interrupt.h> -+#include <linux/debugfs.h> -+#include <linux/kthread.h> +#include <linux/msi.h> -+#include <linux/net_tstamp.h> ++#include <linux/kthread.h> +#include <linux/iommu.h> -+ -+#include "../../fsl-mc/include/dpbp.h" -+#include "../../fsl-mc/include/dpcon.h" -+#include "../../fsl-mc/include/mc.h" -+#include "../../fsl-mc/include/mc-sys.h" ++#include <linux/net_tstamp.h> ++#include <linux/bpf.h> ++#include <linux/filter.h> ++#include <linux/atomic.h> ++#include <net/sock.h> ++#include <linux/fsl/mc.h> +#include "dpaa2-eth.h" -+#include "dpkg.h" ++#include "dpaa2-eth-ceetm.h" + +/* CREATE_TRACE_POINTS only needs to be defined once. Other dpa files + * using trace events only need to #include <trace/events/sched.h> @@ -1263,7 +2745,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +const char dpaa2_eth_drv_version[] = "0.1"; + -+void *dpaa2_eth_iova_to_virt(struct iommu_domain *domain, dma_addr_t iova_addr) ++static void *dpaa2_iova_to_virt(struct iommu_domain *domain, ++ dma_addr_t iova_addr) +{ + phys_addr_t phys_addr; + @@ -1309,26 +2792,26 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + if (fd_format == dpaa2_fd_single) + goto free_buf; + else if (fd_format != dpaa2_fd_sg) -+ /* we don't support any other format */ ++ /* We don't support any other format */ + return; + -+ /* For S/G frames, we first need to free all SG entries */ ++ /* For S/G frames, we first need to free all SG entries ++ * except the first one, which was taken care of already ++ */ + sgt = vaddr + dpaa2_fd_get_offset(fd); -+ for (i = 0; i < DPAA2_ETH_MAX_SG_ENTRIES; i++) { ++ for (i = 1; i < DPAA2_ETH_MAX_SG_ENTRIES; i++) { + addr = dpaa2_sg_get_addr(&sgt[i]); -+ sg_vaddr = dpaa2_eth_iova_to_virt(priv->iommu_domain, addr); -+ ++ sg_vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr); + dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE, -+ DMA_FROM_DEVICE); -+ -+ put_page(virt_to_head_page(sg_vaddr)); ++ DMA_BIDIRECTIONAL); + ++ skb_free_frag(sg_vaddr); + if (dpaa2_sg_is_final(&sgt[i])) + break; + } + +free_buf: -+ put_page(virt_to_head_page(vaddr)); ++ skb_free_frag(vaddr); +} + +/* Build a linear skb based on a single-buffer frame descriptor */ @@ -1377,17 +2860,29 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + /* Get the address and length from the S/G entry */ + sg_addr = dpaa2_sg_get_addr(sge); -+ sg_vaddr = dpaa2_eth_iova_to_virt(priv->iommu_domain, sg_addr); ++ sg_vaddr = dpaa2_iova_to_virt(priv->iommu_domain, sg_addr); + dma_unmap_single(dev, sg_addr, DPAA2_ETH_RX_BUF_SIZE, -+ DMA_FROM_DEVICE); ++ DMA_BIDIRECTIONAL); + + sg_length = dpaa2_sg_get_len(sge); + + if (i == 0) { + /* We build the skb around the first data buffer */ + skb = build_skb(sg_vaddr, DPAA2_ETH_SKB_SIZE); -+ if (unlikely(!skb)) -+ goto err_build; ++ if (unlikely(!skb)) { ++ /* Free the first SG entry now, since we already ++ * unmapped it and obtained the virtual address ++ */ ++ skb_free_frag(sg_vaddr); ++ ++ /* We still need to subtract the buffers used ++ * by this FD from our software counter ++ */ ++ while (!dpaa2_sg_is_final(&sgt[i]) && ++ i < DPAA2_ETH_MAX_SG_ENTRIES) ++ i++; ++ break; ++ } + + sg_offset = dpaa2_sg_get_offset(sge); + skb_reserve(skb, sg_offset); @@ -1414,21 +2909,57 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + break; + } + ++ WARN_ONCE(i == DPAA2_ETH_MAX_SG_ENTRIES, "Final bit not set in SGT"); ++ + /* Count all data buffers + SG table buffer */ + ch->buf_count -= i + 2; + + return skb; ++} + -+err_build: -+ /* We still need to subtract the buffers used by this FD from our -+ * software counter -+ */ -+ for (i = 0; i < DPAA2_ETH_MAX_SG_ENTRIES; i++) -+ if (dpaa2_sg_is_final(&sgt[i])) ++static int dpaa2_eth_xdp_tx(struct dpaa2_eth_priv *priv, ++ struct dpaa2_fd *fd, ++ void *buf_start, ++ u16 queue_id) ++{ ++ struct dpaa2_eth_fq *fq; ++ struct rtnl_link_stats64 *percpu_stats; ++ struct dpaa2_eth_drv_stats *percpu_extras; ++ struct dpaa2_faead *faead; ++ u32 ctrl, frc; ++ int i, err; ++ ++ /* Mark the egress frame annotation area as valid */ ++ frc = dpaa2_fd_get_frc(fd); ++ dpaa2_fd_set_frc(fd, frc | DPAA2_FD_FRC_FAEADV); ++ dpaa2_fd_set_ctrl(fd, DPAA2_FD_CTRL_ASAL); ++ ++ ctrl = DPAA2_FAEAD_A4V | DPAA2_FAEAD_A2V | DPAA2_FAEAD_EBDDV; ++ faead = dpaa2_get_faead(buf_start, false); ++ faead->ctrl = cpu_to_le32(ctrl); ++ faead->conf_fqid = 0; ++ ++ percpu_stats = this_cpu_ptr(priv->percpu_stats); ++ percpu_extras = this_cpu_ptr(priv->percpu_extras); ++ ++ fq = &priv->fq[queue_id]; ++ for (i = 0; i < DPAA2_ETH_ENQUEUE_RETRIES; i++) { ++ err = dpaa2_io_service_enqueue_qd(fq->channel->dpio, ++ priv->tx_qdid, 0, ++ fq->tx_qdbin, fd); ++ if (err != -EBUSY) + break; -+ ch->buf_count -= i + 2; ++ } + -+ return NULL; ++ percpu_extras->tx_portal_busy += i; ++ if (unlikely(err)) { ++ percpu_stats->tx_errors++; ++ } else { ++ percpu_stats->tx_packets++; ++ percpu_stats->tx_bytes += dpaa2_fd_get_len(fd); ++ } ++ ++ return err; +} + +static void free_bufs(struct dpaa2_eth_priv *priv, u64 *buf_array, int count) @@ -1439,13 +2970,34 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + for (i = 0; i < count; i++) { + /* Same logic as on regular Rx path */ -+ vaddr = dpaa2_eth_iova_to_virt(priv->iommu_domain, buf_array[i]); ++ vaddr = dpaa2_iova_to_virt(priv->iommu_domain, buf_array[i]); + dma_unmap_single(dev, buf_array[i], DPAA2_ETH_RX_BUF_SIZE, -+ DMA_FROM_DEVICE); -+ put_page(virt_to_head_page(vaddr)); ++ DMA_BIDIRECTIONAL); ++ skb_free_frag(vaddr); + } +} + ++static void release_fd_buf(struct dpaa2_eth_priv *priv, ++ struct dpaa2_eth_channel *ch, ++ dma_addr_t addr) ++{ ++ int err; ++ ++ ch->rel_buf_array[ch->rel_buf_cnt++] = addr; ++ if (likely(ch->rel_buf_cnt < DPAA2_ETH_BUFS_PER_CMD)) ++ return; ++ ++ while ((err = dpaa2_io_service_release(ch->dpio, priv->bpid, ++ ch->rel_buf_array, ++ ch->rel_buf_cnt)) == -EBUSY) ++ cpu_relax(); ++ ++ if (err) ++ free_bufs(priv, ch->rel_buf_array, ch->rel_buf_cnt); ++ ++ ch->rel_buf_cnt = 0; ++} ++ +/* Main Rx frame processing routine */ +static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv, + struct dpaa2_eth_channel *ch, @@ -1463,47 +3015,86 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct dpaa2_fas *fas; + void *buf_data; + u32 status = 0; ++ struct bpf_prog *xdp_prog; ++ struct xdp_buff xdp; ++ u32 xdp_act; + + /* Tracing point */ + trace_dpaa2_rx_fd(priv->net_dev, fd); + -+ vaddr = dpaa2_eth_iova_to_virt(priv->iommu_domain, addr); -+ dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE, DMA_FROM_DEVICE); ++ vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr); ++ dma_sync_single_for_cpu(dev, addr, DPAA2_ETH_RX_BUF_SIZE, ++ DMA_BIDIRECTIONAL); + -+ /* HWA - FAS, timestamp */ -+ fas = dpaa2_eth_get_fas(vaddr); ++ fas = dpaa2_get_fas(vaddr, false); + prefetch(fas); -+ /* data / SG table */ + buf_data = vaddr + dpaa2_fd_get_offset(fd); + prefetch(buf_data); + + percpu_stats = this_cpu_ptr(priv->percpu_stats); + percpu_extras = this_cpu_ptr(priv->percpu_extras); + -+ switch (fd_format) { -+ case dpaa2_fd_single: ++ xdp_prog = READ_ONCE(ch->xdp_prog); ++ ++ if (fd_format == dpaa2_fd_single) { ++ if (xdp_prog) { ++ xdp.data = buf_data; ++ xdp.data_end = buf_data + dpaa2_fd_get_len(fd); ++ /* for now, we don't support changes in header size */ ++ xdp.data_hard_start = buf_data; ++ ++ /* update stats here, as we won't reach the code ++ * that does that for standard frames ++ */ ++ percpu_stats->rx_packets++; ++ percpu_stats->rx_bytes += dpaa2_fd_get_len(fd); ++ ++ xdp_act = bpf_prog_run_xdp(xdp_prog, &xdp); ++ switch (xdp_act) { ++ case XDP_PASS: ++ break; ++ default: ++ bpf_warn_invalid_xdp_action(xdp_act); ++ case XDP_ABORTED: ++ case XDP_DROP: ++ release_fd_buf(priv, ch, addr); ++ goto drop_cnt; ++ case XDP_TX: ++ if (dpaa2_eth_xdp_tx(priv, (struct dpaa2_fd *)fd, vaddr, ++ queue_id)) { ++ dma_unmap_single(dev, addr, ++ DPAA2_ETH_RX_BUF_SIZE, ++ DMA_BIDIRECTIONAL); ++ free_rx_fd(priv, fd, vaddr); ++ ch->buf_count--; ++ } ++ return; ++ } ++ } ++ dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE, ++ DMA_BIDIRECTIONAL); + skb = build_linear_skb(priv, ch, fd, vaddr); -+ break; -+ case dpaa2_fd_sg: ++ } else if (fd_format == dpaa2_fd_sg) { ++ dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE, ++ DMA_BIDIRECTIONAL); + skb = build_frag_skb(priv, ch, buf_data); -+ put_page(virt_to_head_page(vaddr)); ++ skb_free_frag(vaddr); + percpu_extras->rx_sg_frames++; + percpu_extras->rx_sg_bytes += dpaa2_fd_get_len(fd); -+ break; -+ default: ++ } else { + /* We don't support any other format */ -+ goto err_frame_format; ++ goto drop_cnt; + } + + if (unlikely(!skb)) -+ goto err_build_skb; ++ goto drop_fd; + + prefetch(skb->data); + + /* Get the timestamp value */ + if (priv->ts_rx_en) { + struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb); -+ u64 *ns = (u64 *)dpaa2_eth_get_ts(vaddr); ++ u64 *ns = dpaa2_get_ts(vaddr, false); + + *ns = DPAA2_PTP_NOMINAL_FREQ_PERIOD_NS * le64_to_cpup(ns); + memset(shhwtstamps, 0, sizeof(*shhwtstamps)); @@ -1531,9 +3122,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + return; + -+err_build_skb: ++drop_fd: + free_rx_fd(priv, fd, vaddr); -+err_frame_format: ++drop_cnt: + percpu_stats->rx_dropped++; +} + @@ -1553,23 +3144,25 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct rtnl_link_stats64 *percpu_stats; + struct dpaa2_fas *fas; + u32 status = 0; -+ bool check_fas_errors = false; ++ u32 fd_errors; ++ bool has_fas_errors = false; + -+ vaddr = dpaa2_eth_iova_to_virt(priv->iommu_domain, addr); -+ dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE, DMA_FROM_DEVICE); ++ vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr); ++ dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE, DMA_BIDIRECTIONAL); + + /* check frame errors in the FD field */ -+ if (fd->simple.ctrl & DPAA2_FD_RX_ERR_MASK) { -+ check_fas_errors = !!(fd->simple.ctrl & FD_CTRL_FAERR) && -+ !!(dpaa2_fd_get_frc(fd) & DPAA2_FD_FRC_FASV); ++ fd_errors = dpaa2_fd_get_ctrl(fd) & DPAA2_FD_RX_ERR_MASK; ++ if (likely(fd_errors)) { ++ has_fas_errors = (fd_errors & FD_CTRL_FAERR) && ++ !!(dpaa2_fd_get_frc(fd) & DPAA2_FD_FRC_FASV); + if (net_ratelimit()) -+ netdev_dbg(priv->net_dev, "Rx frame FD err: %x08\n", -+ fd->simple.ctrl & DPAA2_FD_RX_ERR_MASK); ++ netdev_dbg(priv->net_dev, "RX frame FD err: %08x\n", ++ fd_errors); + } + + /* check frame errors in the FAS field */ -+ if (check_fas_errors) { -+ fas = dpaa2_eth_get_fas(vaddr); ++ if (has_fas_errors) { ++ fas = dpaa2_get_fas(vaddr, false); + status = le32_to_cpu(fas->status); + if (net_ratelimit()) + netdev_dbg(priv->net_dev, "Rx frame FAS err: 0x%08x\n", @@ -1579,6 +3172,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + percpu_stats = this_cpu_ptr(priv->percpu_stats); + percpu_stats->rx_errors++; ++ ch->buf_count--; +} +#endif + @@ -1613,11 +3207,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + } + + fd = dpaa2_dq_fd(dq); -+ -+ /* prefetch the frame descriptor */ + prefetch(fd); + -+ fq = (struct dpaa2_eth_fq *)dpaa2_dq_fqd_ctx(dq); ++ fq = (struct dpaa2_eth_fq *)(uintptr_t)dpaa2_dq_fqd_ctx(dq); + fq->consume(priv, ch, fd, &ch->napi, fq->flowid); + cleaned++; + } while (!is_last); @@ -1643,18 +3235,21 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +static void enable_tx_tstamp(struct dpaa2_fd *fd, void *buf_start) +{ + struct dpaa2_faead *faead; -+ u32 ctrl; -+ u32 frc; ++ u32 ctrl, frc; + + /* Mark the egress frame annotation area as valid */ + frc = dpaa2_fd_get_frc(fd); + dpaa2_fd_set_frc(fd, frc | DPAA2_FD_FRC_FAEADV); + ++ /* Set hardware annotation size */ ++ ctrl = dpaa2_fd_get_ctrl(fd); ++ dpaa2_fd_set_ctrl(fd, ctrl | DPAA2_FD_CTRL_ASAL); ++ + /* enable UPD (update prepanded data) bit in FAEAD field of + * hardware frame annotation area + */ + ctrl = DPAA2_FAEAD_A2V | DPAA2_FAEAD_UPDV | DPAA2_FAEAD_UPD; -+ faead = dpaa2_eth_get_faead(buf_start); ++ faead = dpaa2_get_faead(buf_start, true); + faead->ctrl = cpu_to_le32(ctrl); +} + @@ -1673,7 +3268,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct scatterlist *scl, *crt_scl; + int num_sg; + int num_dma_bufs; -+ struct dpaa2_fas *fas; + struct dpaa2_eth_swa *swa; + + /* Create and map scatterlist. @@ -1690,7 +3284,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + sg_init_table(scl, nr_frags + 1); + num_sg = skb_to_sgvec(skb, scl, 0, skb->len); -+ num_dma_bufs = dma_map_sg(dev, scl, num_sg, DMA_TO_DEVICE); ++ num_dma_bufs = dma_map_sg(dev, scl, num_sg, DMA_BIDIRECTIONAL); + if (unlikely(!num_dma_bufs)) { + err = -ENOMEM; + goto dma_map_sg_failed; @@ -1698,21 +3292,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + /* Prepare the HW SGT structure */ + sgt_buf_size = priv->tx_data_offset + -+ sizeof(struct dpaa2_sg_entry) * (1 + num_dma_bufs); -+ sgt_buf = kzalloc(sgt_buf_size + DPAA2_ETH_TX_BUF_ALIGN, GFP_ATOMIC); ++ sizeof(struct dpaa2_sg_entry) * num_dma_bufs; ++ sgt_buf = netdev_alloc_frag(sgt_buf_size + DPAA2_ETH_TX_BUF_ALIGN); + if (unlikely(!sgt_buf)) { + err = -ENOMEM; + goto sgt_buf_alloc_failed; + } + sgt_buf = PTR_ALIGN(sgt_buf, DPAA2_ETH_TX_BUF_ALIGN); -+ -+ /* PTA from egress side is passed as is to the confirmation side so -+ * we need to clear some fields here in order to find consistent values -+ * on TX confirmation. We are clearing FAS (Frame Annotation Status) -+ * field from the hardware annotation area -+ */ -+ fas = dpaa2_eth_get_fas(sgt_buf); -+ memset(fas, 0, DPAA2_FAS_SIZE); ++ memset(sgt_buf, 0, sgt_buf_size); + + sgt = (struct dpaa2_sg_entry *)(sgt_buf + priv->tx_data_offset); + @@ -1735,10 +3322,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * all of them on Tx Conf. + */ + swa = (struct dpaa2_eth_swa *)sgt_buf; -+ swa->skb = skb; -+ swa->scl = scl; -+ swa->num_sg = num_sg; -+ swa->num_dma_bufs = num_dma_bufs; ++ swa->type = DPAA2_ETH_SWA_SG; ++ swa->sg.skb = skb; ++ swa->sg.scl = scl; ++ swa->sg.num_sg = num_sg; ++ swa->sg.sgt_size = sgt_buf_size; + + /* Separately map the SGT buffer */ + addr = dma_map_single(dev, sgt_buf, sgt_buf_size, DMA_BIDIRECTIONAL); @@ -1750,8 +3338,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + dpaa2_fd_set_format(fd, dpaa2_fd_sg); + dpaa2_fd_set_addr(fd, addr); + dpaa2_fd_set_len(fd, skb->len); -+ -+ fd->simple.ctrl = DPAA2_FD_CTRL_ASAL | FD_CTRL_PTA; ++ dpaa2_fd_set_ctrl(fd, FD_CTRL_PTA); + + if (priv->ts_tx_en && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) + enable_tx_tstamp(fd, sgt_buf); @@ -1759,9 +3346,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return 0; + +dma_map_single_failed: -+ kfree(sgt_buf); ++ skb_free_frag(sgt_buf); +sgt_buf_alloc_failed: -+ dma_unmap_sg(dev, scl, num_sg, DMA_TO_DEVICE); ++ dma_unmap_sg(dev, scl, num_sg, DMA_BIDIRECTIONAL); +dma_map_sg_failed: + kfree(scl); + return err; @@ -1773,29 +3360,27 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct dpaa2_fd *fd) +{ + struct device *dev = priv->net_dev->dev.parent; -+ u8 *buffer_start; -+ struct sk_buff **skbh; ++ u8 *buffer_start, *aligned_start; ++ struct dpaa2_eth_swa *swa; + dma_addr_t addr; -+ struct dpaa2_fas *fas; + -+ buffer_start = PTR_ALIGN(skb->data - priv->tx_data_offset - -+ DPAA2_ETH_TX_BUF_ALIGN, -+ DPAA2_ETH_TX_BUF_ALIGN); ++ buffer_start = skb->data - dpaa2_eth_needed_headroom(priv, skb); + -+ /* PTA from egress side is passed as is to the confirmation side so -+ * we need to clear some fields here in order to find consistent values -+ * on TX confirmation. We are clearing FAS (Frame Annotation Status) -+ * field from the hardware annotation area ++ /* If there's enough room to align the FD address, do it. ++ * It will help hardware optimize accesses. + */ -+ fas = dpaa2_eth_get_fas(buffer_start); -+ memset(fas, 0, DPAA2_FAS_SIZE); ++ aligned_start = PTR_ALIGN(buffer_start - DPAA2_ETH_TX_BUF_ALIGN, ++ DPAA2_ETH_TX_BUF_ALIGN); ++ if (aligned_start >= skb->head) ++ buffer_start = aligned_start; + + /* Store a backpointer to the skb at the beginning of the buffer + * (in the private data area) such that we can release it + * on Tx confirm + */ -+ skbh = (struct sk_buff **)buffer_start; -+ *skbh = skb; ++ swa = (struct dpaa2_eth_swa *)buffer_start; ++ swa->type = DPAA2_ETH_SWA_SINGLE; ++ swa->single.skb = skb; + + addr = dma_map_single(dev, buffer_start, + skb_tail_pointer(skb) - buffer_start, @@ -1807,8 +3392,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + dpaa2_fd_set_offset(fd, (u16)(skb->data - buffer_start)); + dpaa2_fd_set_len(fd, skb->len); + dpaa2_fd_set_format(fd, dpaa2_fd_single); -+ -+ fd->simple.ctrl = DPAA2_FD_CTRL_ASAL | FD_CTRL_PTA; ++ dpaa2_fd_set_ctrl(fd, FD_CTRL_PTA); + + if (priv->ts_tx_en && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) + enable_tx_tstamp(fd, buffer_start); @@ -1825,59 +3409,41 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * Optionally, return the frame annotation status word (FAS), which needs + * to be checked if we're on the confirmation path. + */ -+static void free_tx_fd(const struct dpaa2_eth_priv *priv, ++static void free_tx_fd(struct dpaa2_eth_priv *priv, + const struct dpaa2_fd *fd, -+ u32 *status, bool in_napi) ++ bool in_napi) +{ + struct device *dev = priv->net_dev->dev.parent; + dma_addr_t fd_addr; -+ struct sk_buff **skbh, *skb; ++ struct sk_buff *skb = NULL; + unsigned char *buffer_start; -+ int unmap_size; -+ struct scatterlist *scl; -+ int num_sg, num_dma_bufs; + struct dpaa2_eth_swa *swa; + u8 fd_format = dpaa2_fd_get_format(fd); -+ struct dpaa2_fas *fas; + + fd_addr = dpaa2_fd_get_addr(fd); -+ skbh = dpaa2_eth_iova_to_virt(priv->iommu_domain, fd_addr); ++ buffer_start = dpaa2_iova_to_virt(priv->iommu_domain, fd_addr); ++ swa = (struct dpaa2_eth_swa *)buffer_start; + -+ /* HWA - FAS, timestamp (for Tx confirmation frames) */ -+ fas = dpaa2_eth_get_fas(skbh); -+ prefetch(fas); -+ -+ switch (fd_format) { -+ case dpaa2_fd_single: -+ skb = *skbh; -+ buffer_start = (unsigned char *)skbh; ++ if (fd_format == dpaa2_fd_single) { ++ skb = swa->single.skb; + /* Accessing the skb buffer is safe before dma unmap, because + * we didn't map the actual skb shell. + */ + dma_unmap_single(dev, fd_addr, + skb_tail_pointer(skb) - buffer_start, + DMA_BIDIRECTIONAL); -+ break; -+ case dpaa2_fd_sg: -+ swa = (struct dpaa2_eth_swa *)skbh; -+ skb = swa->skb; -+ scl = swa->scl; -+ num_sg = swa->num_sg; -+ num_dma_bufs = swa->num_dma_bufs; ++ } else if (fd_format == dpaa2_fd_sg) { ++ skb = swa->sg.skb; + + /* Unmap the scatterlist */ -+ dma_unmap_sg(dev, scl, num_sg, DMA_TO_DEVICE); -+ kfree(scl); ++ dma_unmap_sg(dev, swa->sg.scl, swa->sg.num_sg, DMA_BIDIRECTIONAL); ++ kfree(swa->sg.scl); + + /* Unmap the SGT buffer */ -+ unmap_size = priv->tx_data_offset + -+ sizeof(struct dpaa2_sg_entry) * (1 + num_dma_bufs); -+ dma_unmap_single(dev, fd_addr, unmap_size, DMA_BIDIRECTIONAL); -+ break; -+ default: -+ /* Unsupported format, mark it as errored and give up */ -+ if (status) -+ *status = ~0; ++ dma_unmap_single(dev, fd_addr, swa->sg.sgt_size, ++ DMA_BIDIRECTIONAL); ++ } else { ++ netdev_dbg(priv->net_dev, "Invalid FD format\n"); + return; + } + @@ -1888,43 +3454,38 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + memset(&shhwtstamps, 0, sizeof(shhwtstamps)); + -+ ns = (u64 *)dpaa2_eth_get_ts(skbh); ++ ns = dpaa2_get_ts(buffer_start, true); + *ns = DPAA2_PTP_NOMINAL_FREQ_PERIOD_NS * le64_to_cpup(ns); + shhwtstamps.hwtstamp = ns_to_ktime(*ns); + skb_tstamp_tx(skb, &shhwtstamps); + } + -+ /* Read the status from the Frame Annotation after we unmap the first -+ * buffer but before we free it. The caller function is responsible -+ * for checking the status value. -+ */ -+ if (status) -+ *status = le32_to_cpu(fas->status); -+ -+ /* Free SGT buffer kmalloc'ed on tx */ ++ /* Free SGT buffer allocated on tx */ + if (fd_format != dpaa2_fd_single) -+ kfree(skbh); ++ skb_free_frag(buffer_start); + + /* Move on with skb release */ + napi_consume_skb(skb, in_napi); +} + -+static int dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev) ++static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev) +{ + struct dpaa2_eth_priv *priv = netdev_priv(net_dev); + struct device *dev = net_dev->dev.parent; + struct dpaa2_fd fd; + struct rtnl_link_stats64 *percpu_stats; + struct dpaa2_eth_drv_stats *percpu_extras; ++ unsigned int needed_headroom; + struct dpaa2_eth_fq *fq; -+ u16 queue_mapping = skb_get_queue_mapping(skb); -+ int err, i; ++ u16 queue_mapping; ++ int err, i, ch_id = 0, qpri = 0; + -+ /* If we're congested, stop this tx queue; transmission of the -+ * current skb happens regardless of congestion state -+ */ ++ queue_mapping = skb_get_queue_mapping(skb); + fq = &priv->fq[queue_mapping]; + ++ /* If we're congested, stop this tx queue; transmission of ++ * the current skb happens regardless of congestion state ++ */ + dma_sync_single_for_cpu(dev, priv->cscn_dma, + DPAA2_CSCN_SIZE, DMA_FROM_DEVICE); + if (unlikely(dpaa2_cscn_state_congested(priv->cscn_mem))) { @@ -1935,14 +3496,19 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + percpu_stats = this_cpu_ptr(priv->percpu_stats); + percpu_extras = this_cpu_ptr(priv->percpu_extras); + -+ if (unlikely(skb_headroom(skb) < DPAA2_ETH_NEEDED_HEADROOM(priv))) { ++ /* For non-linear skb we don't need a minimum headroom */ ++ needed_headroom = dpaa2_eth_needed_headroom(priv, skb); ++ if (skb_headroom(skb) < needed_headroom) { + struct sk_buff *ns; + -+ ns = skb_realloc_headroom(skb, DPAA2_ETH_NEEDED_HEADROOM(priv)); ++ ns = skb_realloc_headroom(skb, needed_headroom); + if (unlikely(!ns)) { + percpu_stats->tx_dropped++; + goto err_alloc_headroom; + } ++ percpu_extras->tx_reallocs++; ++ if (skb->sk) ++ skb_set_owner_w(ns, skb->sk); + dev_kfree_skb(skb); + skb = ns; + } @@ -1976,13 +3542,16 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + /* Tracing point */ + trace_dpaa2_tx_fd(net_dev, &fd); + ++ if (dpaa2_eth_ceetm_is_enabled(priv)) { ++ err = dpaa2_ceetm_classify(skb, net_dev->qdisc, &ch_id, &qpri); ++ if (err) ++ goto err_ceetm_classify; ++ } ++ + for (i = 0; i < DPAA2_ETH_ENQUEUE_RETRIES; i++) { -+ err = dpaa2_io_service_enqueue_qd(NULL, priv->tx_qdid, 0, ++ err = dpaa2_io_service_enqueue_qd(fq->channel->dpio, ++ priv->tx_qdid, qpri, + fq->tx_qdbin, &fd); -+ /* TODO: This doesn't work. Check on simulator. -+ * err = dpaa2_io_service_enqueue_fq(NULL, -+ * priv->fq[0].fqid_tx, &fd); -+ */ + if (err != -EBUSY) + break; + } @@ -1990,7 +3559,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + if (unlikely(err < 0)) { + percpu_stats->tx_errors++; + /* Clean up everything, including freeing the skb */ -+ free_tx_fd(priv, &fd, NULL, false); ++ free_tx_fd(priv, &fd, false); + } else { + percpu_stats->tx_packets++; + percpu_stats->tx_bytes += dpaa2_fd_get_len(&fd); @@ -1998,6 +3567,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + return NETDEV_TX_OK; + ++err_ceetm_classify: ++ free_tx_fd(priv, &fd, false); +err_build_fd: +err_alloc_headroom: + dev_kfree_skb(skb); @@ -2015,9 +3586,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct device *dev = priv->net_dev->dev.parent; + struct rtnl_link_stats64 *percpu_stats; + struct dpaa2_eth_drv_stats *percpu_extras; -+ u32 status = 0; -+ bool errors = !!(fd->simple.ctrl & DPAA2_FD_TX_ERR_MASK); -+ bool check_fas_errors = false; ++ u32 fd_errors; + + /* Tracing point */ + trace_dpaa2_tx_conf_fd(priv->net_dev, fd); @@ -2034,28 +3603,20 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + netif_tx_wake_all_queues(priv->net_dev); + } + -+ /* check frame errors in the FD field */ -+ if (unlikely(errors)) { -+ check_fas_errors = !!(fd->simple.ctrl & FD_CTRL_FAERR) && -+ !!(dpaa2_fd_get_frc(fd) & DPAA2_FD_FRC_FASV); -+ if (net_ratelimit()) -+ netdev_dbg(priv->net_dev, "Tx frame FD err: %x08\n", -+ fd->simple.ctrl & DPAA2_FD_TX_ERR_MASK); -+ } ++ /* Check frame errors in the FD field */ ++ fd_errors = dpaa2_fd_get_ctrl(fd) & DPAA2_FD_TX_ERR_MASK; ++ free_tx_fd(priv, fd, true); + -+ free_tx_fd(priv, fd, check_fas_errors ? &status : NULL, true); -+ -+ /* if there are no errors, we're done */ -+ if (likely(!errors)) ++ if (likely(!fd_errors)) + return; + ++ if (net_ratelimit()) ++ netdev_dbg(priv->net_dev, "TX frame FD error: 0x%08x\n", ++ fd_errors); ++ + percpu_stats = this_cpu_ptr(priv->percpu_stats); + /* Tx-conf logically pertains to the egress path. */ + percpu_stats->tx_errors++; -+ -+ if (net_ratelimit()) -+ netdev_dbg(priv->net_dev, "Tx frame FAS err: %x08\n", -+ status & DPAA2_FAS_TX_ERR_MASK); +} + +static int set_rx_csum(struct dpaa2_eth_priv *priv, bool enable) @@ -2066,7 +3627,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + DPNI_OFF_RX_L3_CSUM, enable); + if (err) { + netdev_err(priv->net_dev, -+ "dpni_set_offload() DPNI_OFF_RX_L3_CSUM failed\n"); ++ "dpni_set_offload(RX_L3_CSUM) failed\n"); + return err; + } + @@ -2074,7 +3635,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + DPNI_OFF_RX_L4_CSUM, enable); + if (err) { + netdev_err(priv->net_dev, -+ "dpni_set_offload() DPNI_OFF_RX_L4_CSUM failed\n"); ++ "dpni_set_offload(RX_L4_CSUM) failed\n"); + return err; + } + @@ -2088,16 +3649,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + err = dpni_set_offload(priv->mc_io, 0, priv->mc_token, + DPNI_OFF_TX_L3_CSUM, enable); + if (err) { -+ netdev_err(priv->net_dev, -+ "dpni_set_offload() DPNI_OFF_RX_L3_CSUM failed\n"); ++ netdev_err(priv->net_dev, "dpni_set_offload(TX_L3_CSUM) failed\n"); + return err; + } + + err = dpni_set_offload(priv->mc_io, 0, priv->mc_token, + DPNI_OFF_TX_L4_CSUM, enable); + if (err) { -+ netdev_err(priv->net_dev, -+ "dpni_set_offload() DPNI_OFF_RX_L4_CSUM failed\n"); ++ netdev_err(priv->net_dev, "dpni_set_offload(TX_L4_CSUM) failed\n"); + return err; + } + @@ -2107,7 +3666,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +/* Perform a single release command to add buffers + * to the specified buffer pool + */ -+static int add_bufs(struct dpaa2_eth_priv *priv, u16 bpid) ++static int add_bufs(struct dpaa2_eth_priv *priv, ++ struct dpaa2_eth_channel *ch, u16 bpid) +{ + struct device *dev = priv->net_dev->dev.parent; + u64 buf_array[DPAA2_ETH_BUFS_PER_CMD]; @@ -2117,16 +3677,16 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + for (i = 0; i < DPAA2_ETH_BUFS_PER_CMD; i++) { + /* Allocate buffer visible to WRIOP + skb shared info + -+ * alignment padding. ++ * alignment padding + */ -+ buf = napi_alloc_frag(DPAA2_ETH_BUF_RAW_SIZE(priv)); ++ buf = napi_alloc_frag(dpaa2_eth_buf_raw_size(priv)); + if (unlikely(!buf)) + goto err_alloc; + + buf = PTR_ALIGN(buf, priv->rx_buf_align); + + addr = dma_map_single(dev, buf, DPAA2_ETH_RX_BUF_SIZE, -+ DMA_FROM_DEVICE); ++ DMA_BIDIRECTIONAL); + if (unlikely(dma_mapping_error(dev, addr))) + goto err_map; + @@ -2134,21 +3694,21 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + /* tracing point */ + trace_dpaa2_eth_buf_seed(priv->net_dev, -+ buf, DPAA2_ETH_BUF_RAW_SIZE(priv), ++ buf, dpaa2_eth_buf_raw_size(priv), + addr, DPAA2_ETH_RX_BUF_SIZE, + bpid); + } + +release_bufs: + /* In case the portal is busy, retry until successful */ -+ while ((err = dpaa2_io_service_release(NULL, bpid, ++ while ((err = dpaa2_io_service_release(ch->dpio, bpid, + buf_array, i)) == -EBUSY) + cpu_relax(); + + /* If release command failed, clean up and bail out; not much + * else we can do about it + */ -+ if (unlikely(err)) { ++ if (err) { + free_bufs(priv, buf_array, i); + return 0; + } @@ -2156,7 +3716,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return i; + +err_map: -+ put_page(virt_to_head_page(buf)); ++ skb_free_frag(buf); +err_alloc: + /* If we managed to allocate at least some buffers, release them */ + if (i) @@ -2179,9 +3739,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + preempt_disable(); + for (j = 0; j < priv->num_channels; j++) { + priv->channel[j]->buf_count = 0; -+ for (i = 0; i < priv->num_bufs; ++ for (i = 0; i < priv->max_bufs_per_ch; + i += DPAA2_ETH_BUFS_PER_CMD) { -+ new_count = add_bufs(priv, bpid); ++ new_count = add_bufs(priv, priv->channel[j], bpid); + priv->channel[j]->buf_count += new_count; + + if (new_count < DPAA2_ETH_BUFS_PER_CMD) { @@ -2236,15 +3796,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return 0; + + do { -+ new_count = add_bufs(priv, bpid); ++ new_count = add_bufs(priv, ch, bpid); + if (unlikely(!new_count)) { + /* Out of memory; abort for now, we'll try later on */ + break; + } + ch->buf_count += new_count; -+ } while (ch->buf_count < priv->num_bufs); ++ } while (ch->buf_count < priv->max_bufs_per_ch); + -+ if (unlikely(ch->buf_count < priv->num_bufs)) ++ if (unlikely(ch->buf_count < priv->max_bufs_per_ch)) + return -ENOMEM; + + return 0; @@ -2257,7 +3817,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + /* Retry while portal is busy */ + do { -+ err = dpaa2_io_service_pull_channel(NULL, ch->ch_id, ch->store); ++ err = dpaa2_io_service_pull_channel(ch->dpio, ch->ch_id, ++ ch->store); + dequeues++; + cpu_relax(); + } while (err == -EBUSY); @@ -2278,7 +3839,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +static int dpaa2_eth_poll(struct napi_struct *napi, int budget) +{ + struct dpaa2_eth_channel *ch; -+ int rx_cleaned = 0, tx_conf_cleaned = 0; ++ int rx_cleaned = 0, tx_conf_cleaned = 0; + bool store_cleaned; + struct dpaa2_eth_priv *priv; + int err; @@ -2306,13 +3867,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + } while (store_cleaned); + + /* We didn't consume the entire budget, finish napi and -+ * re-enable data availability notifications. ++ * re-enable data availability notifications + */ + napi_complete(napi); + do { -+ err = dpaa2_io_service_rearm(NULL, &ch->nctx); ++ err = dpaa2_io_service_rearm(ch->dpio, &ch->nctx); + cpu_relax(); + } while (err == -EBUSY); ++ WARN_ONCE(err, "CDAN notifications rearm failed on core %d", ++ ch->nctx.desired_cpu); + + return max(rx_cleaned, 1); +} @@ -2364,7 +3927,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + netif_carrier_off(priv->net_dev); + } + -+ netdev_info(priv->net_dev, "Link Event: state %s", ++ netdev_info(priv->net_dev, "Link Event: state %s\n", + state.up ? "up" : "down"); + + return 0; @@ -2397,10 +3960,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + priv->dpbp_dev->obj_desc.id, priv->bpid); + } + -+ if (priv->tx_pause_frames) -+ priv->refill_thresh = priv->num_bufs - DPAA2_ETH_BUFS_PER_CMD; -+ else -+ priv->refill_thresh = DPAA2_ETH_REFILL_THRESH_TD; ++ priv->refill_thresh = DPAA2_ETH_REFILL_THRESH(priv); + + err = dpni_enable(priv->mc_io, 0, priv->mc_token); + if (err < 0) { @@ -2431,6 +3991,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct dpaa2_eth_priv *priv = netdev_priv(net_dev); + int dpni_enabled; + int retries = 10, i; ++ int err = 0; + + netif_tx_stop_all_queues(net_dev); + netif_carrier_off(net_dev); @@ -2442,20 +4003,21 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + dpni_disable(priv->mc_io, 0, priv->mc_token); + dpni_is_enabled(priv->mc_io, 0, priv->mc_token, &dpni_enabled); + if (dpni_enabled) -+ /* Allow the MC some slack */ ++ /* Allow the hardware some slack */ + msleep(100); + } while (dpni_enabled && --retries); + if (!retries) { + netdev_warn(net_dev, "Retry count exceeded disabling DPNI\n"); -+ /* Must go on and disable NAPI nonetheless, so we don't crash at -+ * the next "ifconfig up" ++ /* Must go on and finish processing pending frames, so we don't ++ * crash at the next "ifconfig up" + */ ++ err = -ETIMEDOUT; + } + + priv->refill_thresh = 0; + + /* Wait for all running napi poll routines to finish, so that no -+ * new refill operations are started. ++ * new refill operations are started + */ + for (i = 0; i < priv->num_channels; i++) + napi_synchronize(&priv->channel[i]->napi); @@ -2463,7 +4025,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + /* Empty the buffer pool */ + drain_pool(priv); + -+ return 0; ++ return err; +} + +static int dpaa2_eth_init(struct net_device *net_dev) @@ -2538,25 +4100,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return stats; +} + -+static int dpaa2_eth_change_mtu(struct net_device *net_dev, int mtu) -+{ -+ struct dpaa2_eth_priv *priv = netdev_priv(net_dev); -+ int err; -+ -+ /* Set the maximum Rx frame length to match the transmit side; -+ * account for L2 headers when computing the MFL -+ */ -+ err = dpni_set_max_frame_length(priv->mc_io, 0, priv->mc_token, -+ (u16)DPAA2_ETH_L2_MAX_FRM(mtu)); -+ if (err) { -+ netdev_err(net_dev, "dpni_set_max_frame_length() failed\n"); -+ return err; -+ } -+ -+ net_dev->mtu = mtu; -+ return 0; -+} -+ +/* Copy mac unicast addresses from @net_dev to @priv. + * Its sole purpose is to make dpaa2_eth_set_rx_mode() more readable. + */ @@ -2621,7 +4164,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + } + if (mc_count + uc_count > max_mac) { + netdev_info(net_dev, -+ "Unicast + Multicast addr count reached %d, max allowed is %d; forcing promisc\n", ++ "Unicast + multicast addr count reached %d, max allowed is %d; forcing promisc\n", + uc_count + mc_count, max_mac); + goto force_mc_promisc; + } @@ -2757,6 +4300,134 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return -EINVAL; +} + ++static int set_buffer_layout(struct dpaa2_eth_priv *priv) ++{ ++ struct device *dev = priv->net_dev->dev.parent; ++ struct dpni_buffer_layout buf_layout = {0}; ++ int err; ++ ++ /* We need to check for WRIOP version 1.0.0, but depending on the MC ++ * version, this number is not always provided correctly on rev1. ++ * We need to check for both alternatives in this situation. ++ */ ++ if (priv->dpni_attrs.wriop_version == DPAA2_WRIOP_VERSION(0, 0, 0) || ++ priv->dpni_attrs.wriop_version == DPAA2_WRIOP_VERSION(1, 0, 0)) ++ priv->rx_buf_align = DPAA2_ETH_RX_BUF_ALIGN_REV1; ++ else ++ priv->rx_buf_align = DPAA2_ETH_RX_BUF_ALIGN; ++ ++ /* tx buffer */ ++ buf_layout.pass_timestamp = true; ++ buf_layout.private_data_size = DPAA2_ETH_SWA_SIZE; ++ buf_layout.options = DPNI_BUF_LAYOUT_OPT_TIMESTAMP | ++ DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE; ++ err = dpni_set_buffer_layout(priv->mc_io, 0, priv->mc_token, ++ DPNI_QUEUE_TX, &buf_layout); ++ if (err) { ++ dev_err(dev, "dpni_set_buffer_layout(TX) failed\n"); ++ return err; ++ } ++ ++ /* tx-confirm buffer */ ++ buf_layout.options = DPNI_BUF_LAYOUT_OPT_TIMESTAMP; ++ err = dpni_set_buffer_layout(priv->mc_io, 0, priv->mc_token, ++ DPNI_QUEUE_TX_CONFIRM, &buf_layout); ++ if (err) { ++ dev_err(dev, "dpni_set_buffer_layout(TX_CONF) failed\n"); ++ return err; ++ } ++ ++ /* Now that we've set our tx buffer layout, retrieve the minimum ++ * required tx data offset. ++ */ ++ err = dpni_get_tx_data_offset(priv->mc_io, 0, priv->mc_token, ++ &priv->tx_data_offset); ++ if (err) { ++ dev_err(dev, "dpni_get_tx_data_offset() failed\n"); ++ return err; ++ } ++ ++ if ((priv->tx_data_offset % 64) != 0) ++ dev_warn(dev, "Tx data offset (%d) not a multiple of 64B\n", ++ priv->tx_data_offset); ++ ++ /* rx buffer */ ++ buf_layout.pass_frame_status = true; ++ buf_layout.pass_parser_result = true; ++ buf_layout.data_align = priv->rx_buf_align; ++ buf_layout.private_data_size = 0; ++ buf_layout.data_head_room = dpaa2_eth_rx_headroom(priv); ++ buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT | ++ DPNI_BUF_LAYOUT_OPT_FRAME_STATUS | ++ DPNI_BUF_LAYOUT_OPT_DATA_ALIGN | ++ DPNI_BUF_LAYOUT_OPT_DATA_HEAD_ROOM | ++ DPNI_BUF_LAYOUT_OPT_TIMESTAMP; ++ err = dpni_set_buffer_layout(priv->mc_io, 0, priv->mc_token, ++ DPNI_QUEUE_RX, &buf_layout); ++ if (err) { ++ dev_err(dev, "dpni_set_buffer_layout(RX) failed\n"); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int dpaa2_eth_set_xdp(struct net_device *net_dev, struct bpf_prog *prog) ++{ ++ struct dpaa2_eth_priv *priv = netdev_priv(net_dev); ++ struct dpaa2_eth_channel *ch; ++ struct bpf_prog *old_prog; ++ int i, err; ++ ++ /* No support for SG frames */ ++ if (DPAA2_ETH_L2_MAX_FRM(net_dev->mtu) > DPAA2_ETH_RX_BUF_SIZE) ++ return -EINVAL; ++ ++ if (netif_running(net_dev)) { ++ err = dpaa2_eth_stop(net_dev); ++ if (err) ++ return err; ++ } ++ ++ if (prog) { ++ prog = bpf_prog_add(prog, priv->num_channels - 1); ++ if (IS_ERR(prog)) ++ return PTR_ERR(prog); ++ } ++ ++ priv->has_xdp_prog = !!prog; ++ ++ for (i = 0; i < priv->num_channels; i++) { ++ ch = priv->channel[i]; ++ old_prog = xchg(&ch->xdp_prog, prog); ++ if (old_prog) ++ bpf_prog_put(old_prog); ++ } ++ ++ if (netif_running(net_dev)) { ++ err = dpaa2_eth_open(net_dev); ++ if (err) ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int dpaa2_eth_xdp(struct net_device *dev, struct netdev_xdp *xdp) ++{ ++ struct dpaa2_eth_priv *priv = netdev_priv(dev); ++ ++ switch (xdp->command) { ++ case XDP_SETUP_PROG: ++ return dpaa2_eth_set_xdp(dev, xdp->prog); ++ case XDP_QUERY_PROG: ++ xdp->prog_attached = priv->has_xdp_prog; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ +static const struct net_device_ops dpaa2_eth_ops = { + .ndo_open = dpaa2_eth_open, + .ndo_start_xmit = dpaa2_eth_tx, @@ -2764,10 +4435,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + .ndo_init = dpaa2_eth_init, + .ndo_set_mac_address = dpaa2_eth_set_addr, + .ndo_get_stats64 = dpaa2_eth_get_stats, -+ .ndo_change_mtu = dpaa2_eth_change_mtu, + .ndo_set_rx_mode = dpaa2_eth_set_rx_mode, + .ndo_set_features = dpaa2_eth_set_features, + .ndo_do_ioctl = dpaa2_eth_ioctl, ++ .ndo_xdp = dpaa2_eth_xdp, +}; + +static void cdan_cb(struct dpaa2_io_notification_ctx *ctx) @@ -2800,34 +4471,32 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + err = dpcon_open(priv->mc_io, 0, dpcon->obj_desc.id, &dpcon->mc_handle); + if (err) { + dev_err(dev, "dpcon_open() failed\n"); -+ goto err_open; ++ goto free; + } + + err = dpcon_reset(priv->mc_io, 0, dpcon->mc_handle); + if (err) { + dev_err(dev, "dpcon_reset() failed\n"); -+ goto err_reset; ++ goto close; + } + + err = dpcon_get_attributes(priv->mc_io, 0, dpcon->mc_handle, &attrs); + if (err) { + dev_err(dev, "dpcon_get_attributes() failed\n"); -+ goto err_get_attr; ++ goto close; + } + + err = dpcon_enable(priv->mc_io, 0, dpcon->mc_handle); + if (err) { + dev_err(dev, "dpcon_enable() failed\n"); -+ goto err_enable; ++ goto close; + } + + return dpcon; + -+err_enable: -+err_get_attr: -+err_reset: ++close: + dpcon_close(priv->mc_io, 0, dpcon->mc_handle); -+err_open: ++free: + fsl_mc_object_free(dpcon); + + return NULL; @@ -2880,7 +4549,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +static void free_channel(struct dpaa2_eth_priv *priv, + struct dpaa2_eth_channel *channel) +{ ++ struct bpf_prog *prog; ++ + free_dpcon(priv, channel->dpcon); ++ ++ prog = READ_ONCE(channel->xdp_prog); ++ if (prog) ++ bpf_prog_put(prog); ++ + kfree(channel); +} + @@ -2911,6 +4587,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + if (!channel) { + dev_info(dev, + "No affine channel for cpu %d and above\n", i); ++ err = -ENODEV; + goto err_alloc_ch; + } + @@ -2923,12 +4600,16 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + nctx->desired_cpu = i; + + /* Register the new context */ -+ err = dpaa2_io_service_register(NULL, nctx); ++ channel->dpio = dpaa2_io_service_select(i); ++ err = dpaa2_io_service_register(channel->dpio, nctx); + if (err) { + dev_dbg(dev, "No affine DPIO for cpu %d\n", i); + /* If no affine DPIO for this core, there's probably -+ * none available for next cores either. ++ * none available for next cores either. Signal we want ++ * to retry later, in case the DPIO devices weren't ++ * probed yet. + */ ++ err = -EPROBE_DEFER; + goto err_service_reg; + } + @@ -2957,23 +4638,17 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + break; + } + -+ /* Tx confirmation queues can only be serviced by cpus -+ * with an affine DPIO/channel -+ */ -+ cpumask_copy(&priv->txconf_cpumask, &priv->dpio_cpumask); -+ + return 0; + +err_set_cdan: -+ dpaa2_io_service_deregister(NULL, nctx); ++ dpaa2_io_service_deregister(channel->dpio, nctx); +err_service_reg: + free_channel(priv, channel); +err_alloc_ch: + if (cpumask_empty(&priv->dpio_cpumask)) { -+ dev_dbg(dev, "No cpu with an affine DPIO/DPCON\n"); -+ return -ENODEV; ++ dev_err(dev, "No cpu with an affine DPIO/DPCON\n"); ++ return err; + } -+ cpumask_copy(&priv->txconf_cpumask, &priv->dpio_cpumask); + + dev_info(dev, "Cores %*pbl available for processing ingress traffic\n", + cpumask_pr_args(&priv->dpio_cpumask)); @@ -2989,7 +4664,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + /* deregister CDAN notifications and free channels */ + for (i = 0; i < priv->num_channels; i++) { + ch = priv->channel[i]; -+ dpaa2_io_service_deregister(NULL, &ch->nctx); ++ dpaa2_io_service_deregister(ch->dpio, &ch->nctx); + free_channel(priv, ch); + } +} @@ -3015,7 +4690,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +static void set_fq_affinity(struct dpaa2_eth_priv *priv) +{ + struct device *dev = priv->net_dev->dev.parent; -+ struct cpumask xps_mask = CPU_MASK_NONE; ++ struct cpumask xps_mask; + struct dpaa2_eth_fq *fq; + int rx_cpu, txc_cpu; + int i, err; @@ -3024,8 +4699,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * This may well change at runtime, either through irqbalance or + * through direct user intervention. + */ -+ rx_cpu = cpumask_first(&priv->dpio_cpumask); -+ txc_cpu = cpumask_first(&priv->txconf_cpumask); ++ rx_cpu = txc_cpu = cpumask_first(&priv->dpio_cpumask); + + for (i = 0; i < priv->num_fqs; i++) { + fq = &priv->fq[i]; @@ -3040,18 +4714,19 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + case DPAA2_TX_CONF_FQ: + fq->target_cpu = txc_cpu; + -+ /* register txc_cpu to XPS */ ++ /* Tell the stack to affine to txc_cpu the Tx queue ++ * associated with the confirmation one ++ */ ++ cpumask_clear(&xps_mask); + cpumask_set_cpu(txc_cpu, &xps_mask); + err = netif_set_xps_queue(priv->net_dev, &xps_mask, + fq->flowid); + if (err) -+ dev_info_once(dev, -+ "Tx: error setting XPS queue\n"); -+ cpumask_clear_cpu(txc_cpu, &xps_mask); ++ dev_info_once(dev, "Error setting XPS queue\n"); + -+ txc_cpu = cpumask_next(txc_cpu, &priv->txconf_cpumask); ++ txc_cpu = cpumask_next(txc_cpu, &priv->dpio_cpumask); + if (txc_cpu >= nr_cpu_ids) -+ txc_cpu = cpumask_first(&priv->txconf_cpumask); ++ txc_cpu = cpumask_first(&priv->dpio_cpumask); + break; + default: + dev_err(dev, "Unknown FQ type: %d\n", fq->type); @@ -3064,10 +4739,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +{ + int i, j; + -+ /* We have one TxConf FQ per Tx flow. Tx queues MUST be at the -+ * beginning of the queue array. -+ * Number of Rx and Tx queues are the same. -+ * We only support one traffic class for now. ++ /* We have one TxConf FQ per Tx flow. ++ * The number of Tx and Rx queues is the same. ++ * Tx queues come first in the fq array. + */ + for (i = 0; i < dpaa2_eth_queue_count(priv); i++) { + priv->fq[priv->num_fqs].type = DPAA2_TX_CONF_FQ; @@ -3098,8 +4772,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +{ + int err; + struct fsl_mc_device *dpbp_dev; -+ struct dpbp_attr dpbp_attrs; + struct device *dev = priv->net_dev->dev.parent; ++ struct dpbp_attr dpbp_attrs; + + err = fsl_mc_object_allocate(to_fsl_mc_device(dev), FSL_MC_POOL_DPBP, + &dpbp_dev); @@ -3135,9 +4809,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + dev_err(dev, "dpbp_get_attributes() failed\n"); + goto err_get_attr; + } -+ + priv->bpid = dpbp_attrs.bpid; -+ priv->num_bufs = DPAA2_ETH_NUM_BUFS_FC / priv->num_channels; ++ ++ /* By default we start with flow control enabled */ ++ priv->max_bufs_per_ch = DPAA2_ETH_NUM_BUFS_FC / priv->num_channels; + + return 0; + @@ -3162,12 +4837,13 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +static int setup_tx_congestion(struct dpaa2_eth_priv *priv) +{ -+ struct dpni_congestion_notification_cfg cong_notif_cfg = { 0 }; ++ struct dpni_congestion_notification_cfg notif_cfg = {0}; + struct device *dev = priv->net_dev->dev.parent; + int err; + + priv->cscn_unaligned = kzalloc(DPAA2_CSCN_SIZE + DPAA2_CSCN_ALIGN, + GFP_KERNEL); ++ + if (!priv->cscn_unaligned) + return -ENOMEM; + @@ -3180,17 +4856,16 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + goto err_dma_map; + } + -+ cong_notif_cfg.units = DPNI_CONGESTION_UNIT_BYTES; -+ cong_notif_cfg.threshold_entry = DPAA2_ETH_TX_CONG_ENTRY_THRESH; -+ cong_notif_cfg.threshold_exit = DPAA2_ETH_TX_CONG_EXIT_THRESH; -+ cong_notif_cfg.message_ctx = (u64)priv; -+ cong_notif_cfg.message_iova = priv->cscn_dma; -+ cong_notif_cfg.notification_mode = DPNI_CONG_OPT_WRITE_MEM_ON_ENTER | -+ DPNI_CONG_OPT_WRITE_MEM_ON_EXIT | -+ DPNI_CONG_OPT_COHERENT_WRITE; ++ notif_cfg.units = DPNI_CONGESTION_UNIT_BYTES; ++ notif_cfg.threshold_entry = DPAA2_ETH_TX_CONG_ENTRY_THRESH; ++ notif_cfg.threshold_exit = DPAA2_ETH_TX_CONG_EXIT_THRESH; ++ notif_cfg.message_ctx = (u64)priv; ++ notif_cfg.message_iova = priv->cscn_dma; ++ notif_cfg.notification_mode = DPNI_CONG_OPT_WRITE_MEM_ON_ENTER | ++ DPNI_CONG_OPT_WRITE_MEM_ON_EXIT | ++ DPNI_CONG_OPT_COHERENT_WRITE; + err = dpni_set_congestion_notification(priv->mc_io, 0, priv->mc_token, -+ DPNI_QUEUE_TX, 0, -+ &cong_notif_cfg); ++ DPNI_QUEUE_TX, 0, ¬if_cfg); + if (err) { + dev_err(dev, "dpni_set_congestion_notification failed\n"); + goto err_set_cong; @@ -3212,20 +4887,32 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct device *dev = &ls_dev->dev; + struct dpaa2_eth_priv *priv; + struct net_device *net_dev; -+ struct dpni_buffer_layout buf_layout; + struct dpni_link_cfg cfg = {0}; + int err; + + net_dev = dev_get_drvdata(dev); + priv = netdev_priv(net_dev); + -+ priv->dpni_id = ls_dev->obj_desc.id; -+ + /* get a handle for the DPNI object */ -+ err = dpni_open(priv->mc_io, 0, priv->dpni_id, &priv->mc_token); ++ err = dpni_open(priv->mc_io, 0, ls_dev->obj_desc.id, &priv->mc_token); + if (err) { + dev_err(dev, "dpni_open() failed\n"); -+ goto err_open; ++ return err; ++ } ++ ++ /* Check if we can work with this DPNI object */ ++ err = dpni_get_api_version(priv->mc_io, 0, &priv->dpni_ver_major, ++ &priv->dpni_ver_minor); ++ if (err) { ++ dev_err(dev, "dpni_get_api_version() failed\n"); ++ goto close; ++ } ++ if (dpaa2_eth_cmp_dpni_ver(priv, DPNI_VER_MAJOR, DPNI_VER_MINOR) < 0) { ++ dev_err(dev, "DPNI version %u.%u not supported, need >= %u.%u\n", ++ priv->dpni_ver_major, priv->dpni_ver_minor, ++ DPNI_VER_MAJOR, DPNI_VER_MINOR); ++ err = -ENOTSUPP; ++ goto close; + } + + ls_dev->mc_io = priv->mc_io; @@ -3234,130 +4921,47 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + err = dpni_reset(priv->mc_io, 0, priv->mc_token); + if (err) { + dev_err(dev, "dpni_reset() failed\n"); -+ goto err_reset; ++ goto close; + } + + err = dpni_get_attributes(priv->mc_io, 0, priv->mc_token, + &priv->dpni_attrs); -+ + if (err) { + dev_err(dev, "dpni_get_attributes() failed (err=%d)\n", err); -+ goto err_get_attr; -+ } -+ -+ /* due to a limitation in WRIOP 1.0.0 (ERR009354), the Rx buf -+ * align value must be a multiple of 256. -+ */ -+ priv->rx_buf_align = -+ priv->dpni_attrs.wriop_version & 0x3ff ? -+ DPAA2_ETH_RX_BUF_ALIGN : DPAA2_ETH_RX_BUF_ALIGN_V1; -+ -+ /* Update number of logical FQs in netdev */ -+ err = netif_set_real_num_tx_queues(net_dev, -+ dpaa2_eth_queue_count(priv)); -+ if (err) { -+ dev_err(dev, "netif_set_real_num_tx_queues failed (%d)\n", err); -+ goto err_set_tx_queues; ++ goto close; + } + -+ err = netif_set_real_num_rx_queues(net_dev, -+ dpaa2_eth_queue_count(priv)); -+ if (err) { -+ dev_err(dev, "netif_set_real_num_rx_queues failed (%d)\n", err); -+ goto err_set_rx_queues; -+ } -+ -+ /* Configure buffer layouts */ -+ /* rx buffer */ -+ buf_layout.pass_parser_result = true; -+ buf_layout.pass_frame_status = true; -+ buf_layout.private_data_size = DPAA2_ETH_SWA_SIZE; -+ buf_layout.data_align = priv->rx_buf_align; -+ buf_layout.data_head_room = DPAA2_ETH_RX_HEAD_ROOM; -+ buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT | -+ DPNI_BUF_LAYOUT_OPT_FRAME_STATUS | -+ DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE | -+ DPNI_BUF_LAYOUT_OPT_DATA_ALIGN | -+ DPNI_BUF_LAYOUT_OPT_DATA_HEAD_ROOM; -+ err = dpni_set_buffer_layout(priv->mc_io, 0, priv->mc_token, -+ DPNI_QUEUE_RX, &buf_layout); -+ if (err) { -+ dev_err(dev, -+ "dpni_set_buffer_layout(RX) failed\n"); -+ goto err_buf_layout; -+ } -+ -+ /* tx buffer */ -+ buf_layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS | -+ DPNI_BUF_LAYOUT_OPT_TIMESTAMP | -+ DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE; -+ buf_layout.pass_timestamp = true; -+ err = dpni_set_buffer_layout(priv->mc_io, 0, priv->mc_token, -+ DPNI_QUEUE_TX, &buf_layout); -+ if (err) { -+ dev_err(dev, -+ "dpni_set_buffer_layout(TX) failed\n"); -+ goto err_buf_layout; -+ } -+ -+ /* tx-confirm buffer */ -+ buf_layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS | -+ DPNI_BUF_LAYOUT_OPT_TIMESTAMP; -+ err = dpni_set_buffer_layout(priv->mc_io, 0, priv->mc_token, -+ DPNI_QUEUE_TX_CONFIRM, &buf_layout); -+ if (err) { -+ dev_err(dev, "dpni_set_buffer_layout(TX_CONF) failed\n"); -+ goto err_buf_layout; -+ } -+ -+ /* Now that we've set our tx buffer layout, retrieve the minimum -+ * required tx data offset. -+ */ -+ err = dpni_get_tx_data_offset(priv->mc_io, 0, priv->mc_token, -+ &priv->tx_data_offset); -+ if (err) { -+ dev_err(dev, "dpni_get_tx_data_offset() failed (%d)\n", err); -+ goto err_data_offset; -+ } -+ -+ if ((priv->tx_data_offset % 64) != 0) -+ dev_warn(dev, "Tx data offset (%d) not a multiple of 64B", -+ priv->tx_data_offset); ++ err = set_buffer_layout(priv); ++ if (err) ++ goto close; + + /* Enable congestion notifications for Tx queues */ + err = setup_tx_congestion(priv); + if (err) -+ goto err_tx_cong; ++ goto close; + + /* allocate classification rule space */ + priv->cls_rule = kzalloc(sizeof(*priv->cls_rule) * + dpaa2_eth_fs_count(priv), GFP_KERNEL); + if (!priv->cls_rule) -+ goto err_cls_rule; ++ goto close; + + /* Enable flow control */ + cfg.options = DPNI_LINK_OPT_AUTONEG | DPNI_LINK_OPT_PAUSE; -+ priv->tx_pause_frames = 1; -+ ++ priv->tx_pause_frames = true; + err = dpni_set_link_cfg(priv->mc_io, 0, priv->mc_token, &cfg); + if (err) { -+ netdev_err(net_dev, "ERROR %d setting link cfg", err); -+ goto err_set_link_cfg; ++ dev_err(dev, "dpni_set_link_cfg() failed\n"); ++ goto cls_free; + } + + return 0; + -+err_set_link_cfg: -+err_cls_rule: -+err_tx_cong: -+err_data_offset: -+err_buf_layout: -+err_set_rx_queues: -+err_set_tx_queues: -+err_get_attr: -+err_reset: ++cls_free: ++ kfree(priv->cls_rule); ++close: + dpni_close(priv->mc_io, 0, priv->mc_token); -+err_open: ++ + return err; +} + @@ -3379,12 +4983,44 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + kfree(priv->cscn_unaligned); +} + ++static int setup_rx_flow(struct dpaa2_eth_priv *priv, ++ struct dpaa2_eth_fq *fq) ++{ ++ struct device *dev = priv->net_dev->dev.parent; ++ struct dpni_queue queue; ++ struct dpni_queue_id qid; ++ int err; ++ ++ err = dpni_get_queue(priv->mc_io, 0, priv->mc_token, ++ DPNI_QUEUE_RX, fq->tc, fq->flowid, &queue, &qid); ++ if (err) { ++ dev_err(dev, "dpni_get_queue(RX) failed\n"); ++ return err; ++ } ++ ++ fq->fqid = qid.fqid; ++ ++ queue.destination.id = fq->channel->dpcon_id; ++ queue.destination.type = DPNI_DEST_DPCON; ++ queue.destination.priority = 1; ++ queue.user_context = (u64)(uintptr_t)fq; ++ err = dpni_set_queue(priv->mc_io, 0, priv->mc_token, ++ DPNI_QUEUE_RX, fq->tc, fq->flowid, ++ DPNI_QUEUE_OPT_USER_CTX | DPNI_QUEUE_OPT_DEST, ++ &queue); ++ if (err) { ++ dev_err(dev, "dpni_set_queue(RX) failed\n"); ++ return err; ++ } ++ ++ return 0; ++} ++ +static int set_queue_taildrop(struct dpaa2_eth_priv *priv, + struct dpni_taildrop *td) +{ + struct device *dev = priv->net_dev->dev.parent; -+ int err, i; -+ ++ int i, err; + + for (i = 0; i < priv->num_fqs; i++) { + if (priv->fq[i].type != DPAA2_RX_FQ) @@ -3398,6 +5034,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + dev_err(dev, "dpni_set_taildrop() failed (%d)\n", err); + return err; + } ++ ++ dev_dbg(dev, "%s taildrop for Rx group tc %d\n", ++ (td->enable ? "Enabled" : "Disabled"), ++ i); + } + + return 0; @@ -3428,7 +5068,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + dev_err(dev, "dpni_set_taildrop() failed (%d)\n", err); + return err; + } ++ ++ dev_dbg(dev, "%s taildrop for Rx queue id %d tc %d\n", ++ (tc_td->enable ? "Enabled" : "Disabled"), ++ priv->fq[i].flowid, priv->fq[i].tc); + } ++ + return 0; +} + @@ -3449,7 +5094,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + case DPAA2_ETH_TD_NONE: + memset(&td_queue, 0, sizeof(struct dpni_taildrop)); + memset(&td_group, 0, sizeof(struct dpni_taildrop)); -+ priv->num_bufs = DPAA2_ETH_NUM_BUFS_FC / ++ priv->max_bufs_per_ch = DPAA2_ETH_NUM_BUFS_FC / + priv->num_channels; + break; + case DPAA2_ETH_TD_QUEUE: @@ -3458,7 +5103,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + td_queue.units = DPNI_CONGESTION_UNIT_BYTES; + td_queue.threshold = DPAA2_ETH_TAILDROP_THRESH / + dpaa2_eth_tc_count(priv); -+ priv->num_bufs = DPAA2_ETH_NUM_BUFS_TD; ++ priv->max_bufs_per_ch = DPAA2_ETH_NUM_BUFS_PER_CH; + break; + case DPAA2_ETH_TD_GROUP: + memset(&td_queue, 0, sizeof(struct dpni_taildrop)); @@ -3466,7 +5111,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + td_group.units = DPNI_CONGESTION_UNIT_FRAMES; + td_group.threshold = NAPI_POLL_WEIGHT * + dpaa2_eth_queue_count(priv); -+ priv->num_bufs = NAPI_POLL_WEIGHT * ++ priv->max_bufs_per_ch = NAPI_POLL_WEIGHT * + dpaa2_eth_tc_count(priv); + break; + default: @@ -3481,39 +5126,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + if (err) + return err; + -+ priv->refill_thresh = priv->num_bufs - DPAA2_ETH_BUFS_PER_CMD; -+ -+ return 0; -+} -+ -+static int setup_rx_flow(struct dpaa2_eth_priv *priv, -+ struct dpaa2_eth_fq *fq) -+{ -+ struct device *dev = priv->net_dev->dev.parent; -+ struct dpni_queue q = { { 0 } }; -+ struct dpni_queue_id qid; -+ u8 q_opt = DPNI_QUEUE_OPT_USER_CTX | DPNI_QUEUE_OPT_DEST; -+ int err; -+ -+ err = dpni_get_queue(priv->mc_io, 0, priv->mc_token, -+ DPNI_QUEUE_RX, fq->tc, fq->flowid, &q, &qid); -+ if (err) { -+ dev_err(dev, "dpni_get_queue() failed (%d)\n", err); -+ return err; -+ } -+ -+ fq->fqid = qid.fqid; -+ -+ q.destination.id = fq->channel->dpcon_id; -+ q.destination.type = DPNI_DEST_DPCON; -+ q.destination.priority = 1; -+ q.user_context = (u64)fq; -+ err = dpni_set_queue(priv->mc_io, 0, priv->mc_token, -+ DPNI_QUEUE_RX, fq->tc, fq->flowid, q_opt, &q); -+ if (err) { -+ dev_err(dev, "dpni_set_queue() failed (%d)\n", err); -+ return err; -+ } ++ priv->refill_thresh = DPAA2_ETH_REFILL_THRESH(priv); + + return 0; +} @@ -3522,37 +5135,39 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct dpaa2_eth_fq *fq) +{ + struct device *dev = priv->net_dev->dev.parent; -+ struct dpni_queue q = { { 0 } }; ++ struct dpni_queue queue; + struct dpni_queue_id qid; -+ u8 q_opt = DPNI_QUEUE_OPT_USER_CTX | DPNI_QUEUE_OPT_DEST; + int err; + + err = dpni_get_queue(priv->mc_io, 0, priv->mc_token, -+ DPNI_QUEUE_TX, 0, fq->flowid, &q, &qid); ++ DPNI_QUEUE_TX, 0, fq->flowid, &queue, &qid); + if (err) { -+ dev_err(dev, "dpni_get_queue() failed (%d)\n", err); ++ dev_err(dev, "dpni_get_queue(TX) failed\n"); + return err; + } + + fq->tx_qdbin = qid.qdbin; + + err = dpni_get_queue(priv->mc_io, 0, priv->mc_token, -+ DPNI_QUEUE_TX_CONFIRM, 0, fq->flowid, &q, &qid); ++ DPNI_QUEUE_TX_CONFIRM, 0, fq->flowid, ++ &queue, &qid); + if (err) { -+ dev_err(dev, "dpni_get_queue() failed (%d)\n", err); ++ dev_err(dev, "dpni_get_queue(TX_CONF) failed\n"); + return err; + } + + fq->fqid = qid.fqid; + -+ q.destination.id = fq->channel->dpcon_id; -+ q.destination.type = DPNI_DEST_DPCON; -+ q.destination.priority = 0; -+ q.user_context = (u64)fq; ++ queue.destination.id = fq->channel->dpcon_id; ++ queue.destination.type = DPNI_DEST_DPCON; ++ queue.destination.priority = 0; ++ queue.user_context = (u64)(uintptr_t)fq; + err = dpni_set_queue(priv->mc_io, 0, priv->mc_token, -+ DPNI_QUEUE_TX_CONFIRM, 0, fq->flowid, q_opt, &q); ++ DPNI_QUEUE_TX_CONFIRM, 0, fq->flowid, ++ DPNI_QUEUE_OPT_USER_CTX | DPNI_QUEUE_OPT_DEST, ++ &queue); + if (err) { -+ dev_err(dev, "dpni_get_queue() failed (%d)\n", err); ++ dev_err(dev, "dpni_set_queue(TX_CONF) failed\n"); + return err; + } + @@ -3594,16 +5209,18 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#endif + +/* default hash key fields */ -+static struct dpaa2_eth_hash_fields default_hash_fields[] = { ++static struct dpaa2_eth_dist_fields default_dist_fields[] = { + { + /* L2 header */ + .rxnfc_field = RXH_L2DA, + .cls_prot = NET_PROT_ETH, + .cls_field = NH_FLD_ETH_DA, ++ .id = DPAA2_ETH_DIST_ETHDST, + .size = 6, + }, { + .cls_prot = NET_PROT_ETH, + .cls_field = NH_FLD_ETH_SA, ++ .id = DPAA2_ETH_DIST_ETHSRC, + .size = 6, + }, { + /* This is the last ethertype field parsed: @@ -3612,28 +5229,33 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + */ + .cls_prot = NET_PROT_ETH, + .cls_field = NH_FLD_ETH_TYPE, ++ .id = DPAA2_ETH_DIST_ETHTYPE, + .size = 2, + }, { + /* VLAN header */ + .rxnfc_field = RXH_VLAN, + .cls_prot = NET_PROT_VLAN, + .cls_field = NH_FLD_VLAN_TCI, ++ .id = DPAA2_ETH_DIST_VLAN, + .size = 2, + }, { + /* IP header */ + .rxnfc_field = RXH_IP_SRC, + .cls_prot = NET_PROT_IP, + .cls_field = NH_FLD_IP_SRC, ++ .id = DPAA2_ETH_DIST_IPSRC, + .size = 4, + }, { + .rxnfc_field = RXH_IP_DST, + .cls_prot = NET_PROT_IP, + .cls_field = NH_FLD_IP_DST, ++ .id = DPAA2_ETH_DIST_IPDST, + .size = 4, + }, { + .rxnfc_field = RXH_L3_PROTO, + .cls_prot = NET_PROT_IP, + .cls_field = NH_FLD_IP_PROTO, ++ .id = DPAA2_ETH_DIST_IPPROTO, + .size = 1, + }, { + /* Using UDP ports, this is functionally equivalent to raw @@ -3642,85 +5264,182 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + .rxnfc_field = RXH_L4_B_0_1, + .cls_prot = NET_PROT_UDP, + .cls_field = NH_FLD_UDP_PORT_SRC, ++ .id = DPAA2_ETH_DIST_L4SRC, + .size = 2, + }, { + .rxnfc_field = RXH_L4_B_2_3, + .cls_prot = NET_PROT_UDP, + .cls_field = NH_FLD_UDP_PORT_DST, ++ .id = DPAA2_ETH_DIST_L4DST, + .size = 2, + }, +}; + -+/* Set RX hash options */ -+static int set_hash(struct dpaa2_eth_priv *priv) ++static int legacy_config_dist_key(struct dpaa2_eth_priv *priv, ++ dma_addr_t key_iova) +{ + struct device *dev = priv->net_dev->dev.parent; -+ struct dpkg_profile_cfg cls_cfg; + struct dpni_rx_tc_dist_cfg dist_cfg; -+ u8 *dma_mem; -+ int i; -+ int err = 0; ++ int i, err; ++ ++ /* In legacy mode, we can't configure flow steering independently */ ++ if (!dpaa2_eth_hash_enabled(priv)) ++ return -EOPNOTSUPP; ++ ++ memset(&dist_cfg, 0, sizeof(dist_cfg)); ++ ++ dist_cfg.key_cfg_iova = key_iova; ++ dist_cfg.dist_size = dpaa2_eth_queue_count(priv); ++ if (dpaa2_eth_fs_enabled(priv)) { ++ dist_cfg.dist_mode = DPNI_DIST_MODE_FS; ++ dist_cfg.fs_cfg.miss_action = DPNI_FS_MISS_HASH; ++ } else { ++ dist_cfg.dist_mode = DPNI_DIST_MODE_HASH; ++ } ++ ++ for (i = 0; i < dpaa2_eth_tc_count(priv); i++) { ++ err = dpni_set_rx_tc_dist(priv->mc_io, 0, priv->mc_token, i, ++ &dist_cfg); ++ if (err) { ++ dev_err(dev, "dpni_set_rx_tc_dist failed\n"); ++ return err; ++ } ++ } ++ ++ return 0; ++} ++ ++static int config_hash_key(struct dpaa2_eth_priv *priv, dma_addr_t key_iova) ++{ ++ struct device *dev = priv->net_dev->dev.parent; ++ struct dpni_rx_dist_cfg dist_cfg; ++ int i, err; ++ ++ if (!dpaa2_eth_hash_enabled(priv)) ++ return -EOPNOTSUPP; ++ ++ memset(&dist_cfg, 0, sizeof(dist_cfg)); ++ ++ dist_cfg.key_cfg_iova = key_iova; ++ dist_cfg.dist_size = dpaa2_eth_queue_count(priv); ++ dist_cfg.enable = true; ++ ++ for (i = 0; i < dpaa2_eth_tc_count(priv); i++) { ++ dist_cfg.tc = i; ++ ++ err = dpni_set_rx_hash_dist(priv->mc_io, 0, ++ priv->mc_token, &dist_cfg); ++ if (err) { ++ dev_err(dev, "dpni_set_rx_hash_dist failed\n"); ++ return err; ++ } ++ } ++ ++ return 0; ++} ++ ++static int config_fs_key(struct dpaa2_eth_priv *priv, dma_addr_t key_iova) ++{ ++ struct device *dev = priv->net_dev->dev.parent; ++ struct dpni_rx_dist_cfg dist_cfg; ++ int i, err; ++ ++ if (!dpaa2_eth_fs_enabled(priv)) ++ return -EOPNOTSUPP; ++ ++ memset(&dist_cfg, 0, sizeof(dist_cfg)); ++ ++ dist_cfg.key_cfg_iova = key_iova; ++ dist_cfg.dist_size = dpaa2_eth_queue_count(priv); ++ dist_cfg.enable = true; ++ ++ for (i = 0; i < dpaa2_eth_tc_count(priv); i++) { ++ dist_cfg.tc = i; ++ ++ err = dpni_set_rx_fs_dist(priv->mc_io, 0, ++ priv->mc_token, &dist_cfg); ++ if (err) { ++ dev_err(dev, "dpni_set_rx_fs_dist failed\n"); ++ return err; ++ } ++ } ++ ++ return 0; ++} ++ ++int dpaa2_eth_set_dist_key(struct dpaa2_eth_priv *priv, ++ enum dpaa2_eth_rx_dist type, u32 key_fields) ++{ ++ struct device *dev = priv->net_dev->dev.parent; ++ struct dpkg_profile_cfg cls_cfg; ++ struct dpkg_extract *key; ++ u32 hash_fields = 0; ++ dma_addr_t key_iova; ++ u8 *key_mem; ++ int i, err; + + memset(&cls_cfg, 0, sizeof(cls_cfg)); + -+ for (i = 0; i < priv->num_hash_fields; i++) { -+ struct dpkg_extract *key = -+ &cls_cfg.extracts[cls_cfg.num_extracts]; ++ for (i = 0; i < priv->num_dist_fields; i++) { ++ if (!(key_fields & priv->dist_fields[i].id)) ++ continue; + ++ key = &cls_cfg.extracts[cls_cfg.num_extracts]; + key->type = DPKG_EXTRACT_FROM_HDR; -+ key->extract.from_hdr.prot = priv->hash_fields[i].cls_prot; ++ key->extract.from_hdr.prot = priv->dist_fields[i].cls_prot; + key->extract.from_hdr.type = DPKG_FULL_FIELD; -+ key->extract.from_hdr.field = priv->hash_fields[i].cls_field; ++ key->extract.from_hdr.field = priv->dist_fields[i].cls_field; + cls_cfg.num_extracts++; + -+ priv->rx_flow_hash |= priv->hash_fields[i].rxnfc_field; ++ hash_fields |= priv->dist_fields[i].rxnfc_field; + } + -+ dma_mem = kzalloc(DPAA2_CLASSIFIER_DMA_SIZE, GFP_DMA | GFP_KERNEL); -+ if (!dma_mem) ++ key_mem = kzalloc(DPAA2_CLASSIFIER_DMA_SIZE, GFP_KERNEL); ++ if (!key_mem) + return -ENOMEM; + -+ err = dpni_prepare_key_cfg(&cls_cfg, dma_mem); ++ err = dpni_prepare_key_cfg(&cls_cfg, key_mem); + if (err) { -+ dev_err(dev, "dpni_prepare_key_cfg() failed (%d)", err); -+ goto err_prep_key; ++ dev_err(dev, "dpni_prepare_key_cfg error %d\n", err); ++ goto free_key; + } + -+ memset(&dist_cfg, 0, sizeof(dist_cfg)); -+ -+ /* Prepare for setting the rx dist */ -+ dist_cfg.key_cfg_iova = dma_map_single(dev, dma_mem, -+ DPAA2_CLASSIFIER_DMA_SIZE, -+ DMA_TO_DEVICE); -+ if (dma_mapping_error(dev, dist_cfg.key_cfg_iova)) { ++ key_iova = dma_map_single(dev, key_mem, DPAA2_CLASSIFIER_DMA_SIZE, ++ DMA_TO_DEVICE); ++ if (dma_mapping_error(dev, key_iova)) { + dev_err(dev, "DMA mapping failed\n"); + err = -ENOMEM; -+ goto err_dma_map; ++ goto free_key; + } + -+ dist_cfg.dist_size = dpaa2_eth_queue_count(priv); -+ if (dpaa2_eth_fs_enabled(priv)) { -+ dist_cfg.dist_mode = DPNI_DIST_MODE_FS; -+ dist_cfg.fs_cfg.miss_action = DPNI_FS_MISS_HASH; -+ } else { -+ dist_cfg.dist_mode = DPNI_DIST_MODE_HASH; ++ switch (type) { ++ case DPAA2_ETH_RX_DIST_LEGACY: ++ err = legacy_config_dist_key(priv, key_iova); ++ break; ++ case DPAA2_ETH_RX_DIST_HASH: ++ err = config_hash_key(priv, key_iova); ++ break; ++ case DPAA2_ETH_RX_DIST_FS: ++ err = config_fs_key(priv, key_iova); ++ break; ++ default: ++ err = -EINVAL; ++ break; + } + -+ for (i = 0; i < dpaa2_eth_tc_count(priv); i++) { -+ err = dpni_set_rx_tc_dist(priv->mc_io, 0, priv->mc_token, i, -+ &dist_cfg); -+ if (err) -+ break; ++ dma_unmap_single(dev, key_iova, DPAA2_CLASSIFIER_DMA_SIZE, ++ DMA_TO_DEVICE); ++ if (err) { ++ if (err != -EOPNOTSUPP) ++ dev_err(dev, "Distribution key config failed\n"); ++ goto free_key; + } + -+ dma_unmap_single(dev, dist_cfg.key_cfg_iova, -+ DPAA2_CLASSIFIER_DMA_SIZE, DMA_TO_DEVICE); -+ if (err) -+ dev_err(dev, "dpni_set_rx_tc_dist() failed (%d)\n", err); ++ if (type != DPAA2_ETH_RX_DIST_FS) ++ priv->rx_hash_fields = hash_fields; + -+err_dma_map: -+err_prep_key: -+ kfree(dma_mem); ++free_key: ++ kfree(key_mem); + return err; +} + @@ -3750,19 +5469,23 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + /* Verify classification options and disable hashing and/or + * flow steering support in case of invalid configuration values + */ -+ priv->hash_fields = default_hash_fields; -+ priv->num_hash_fields = ARRAY_SIZE(default_hash_fields); ++ priv->dist_fields = default_dist_fields; ++ priv->num_dist_fields = ARRAY_SIZE(default_dist_fields); + check_cls_support(priv); + + /* have the interface implicitly distribute traffic based on -+ * a static hash key ++ * a static hash key. Also configure flow steering key, if supported. ++ * Errors here are not blocking, so just let the called function ++ * print its error message and move along. + */ -+ if (dpaa2_eth_hash_enabled(priv)) { -+ err = set_hash(priv); -+ if (err) { -+ dev_err(dev, "Hashing configuration failed\n"); -+ return err; -+ } ++ if (dpaa2_eth_has_legacy_dist(priv)) { ++ dpaa2_eth_set_dist_key(priv, DPAA2_ETH_RX_DIST_LEGACY, ++ DPAA2_ETH_DIST_ALL); ++ } else { ++ dpaa2_eth_set_dist_key(priv, DPAA2_ETH_RX_DIST_HASH, ++ DPAA2_ETH_DIST_DEFAULT_HASH); ++ dpaa2_eth_set_dist_key(priv, DPAA2_ETH_RX_DIST_FS, ++ DPAA2_ETH_DIST_ALL); + } + + /* Configure handling of error frames */ @@ -3776,7 +5499,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + err = dpni_set_errors_behavior(priv->mc_io, 0, priv->mc_token, + &err_cfg); + if (err) { -+ dev_err(dev, "dpni_set_errors_behavior() failed (%d)\n", err); ++ dev_err(dev, "dpni_set_errors_behavior failed\n"); + return err; + } + @@ -3802,8 +5525,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return err; + } + -+ err = dpni_get_qdid(priv->mc_io, 0, priv->mc_token, DPNI_QUEUE_TX, -+ &priv->tx_qdid); ++ err = dpni_get_qdid(priv->mc_io, 0, priv->mc_token, ++ DPNI_QUEUE_TX, &priv->tx_qdid); + if (err) { + dev_err(dev, "dpni_get_qdid() failed\n"); + return err; @@ -3848,68 +5571,61 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + dpaa2_io_store_destroy(priv->channel[i]->store); +} + -+static int netdev_init(struct net_device *net_dev) ++static int set_mac_addr(struct dpaa2_eth_priv *priv) +{ -+ int err; ++ struct net_device *net_dev = priv->net_dev; + struct device *dev = net_dev->dev.parent; -+ struct dpaa2_eth_priv *priv = netdev_priv(net_dev); + u8 mac_addr[ETH_ALEN], dpni_mac_addr[ETH_ALEN]; -+ u8 bcast_addr[ETH_ALEN]; -+ u16 rx_headroom, rx_req_headroom; -+ -+ net_dev->netdev_ops = &dpaa2_eth_ops; ++ int err; + + /* Get firmware address, if any */ + err = dpni_get_port_mac_addr(priv->mc_io, 0, priv->mc_token, mac_addr); + if (err) { -+ dev_err(dev, "dpni_get_port_mac_addr() failed (%d)\n", err); ++ dev_err(dev, "dpni_get_port_mac_addr() failed\n"); + return err; + } + -+ /* Get DPNI atttributes address, if any */ ++ /* Get DPNI attributes address, if any */ + err = dpni_get_primary_mac_addr(priv->mc_io, 0, priv->mc_token, + dpni_mac_addr); + if (err) { -+ dev_err(dev, "dpni_get_primary_mac_addr() failed (%d)\n", err); ++ dev_err(dev, "dpni_get_primary_mac_addr() failed\n"); + return err; + } + + /* First check if firmware has any address configured by bootloader */ + if (!is_zero_ether_addr(mac_addr)) { -+ /* If the DPMAC addr != the DPNI addr, update it */ ++ /* If the DPMAC addr != DPNI addr, update it */ + if (!ether_addr_equal(mac_addr, dpni_mac_addr)) { + err = dpni_set_primary_mac_addr(priv->mc_io, 0, + priv->mc_token, + mac_addr); + if (err) { -+ dev_err(dev, -+ "dpni_set_primary_mac_addr() failed (%d)\n", -+ err); ++ dev_err(dev, "dpni_set_primary_mac_addr() failed\n"); + return err; + } + } + memcpy(net_dev->dev_addr, mac_addr, net_dev->addr_len); + } else if (is_zero_ether_addr(dpni_mac_addr)) { -+ /* Fills in net_dev->dev_addr, as required by -+ * register_netdevice() ++ /* No MAC address configured, fill in net_dev->dev_addr ++ * with a random one + */ + eth_hw_addr_random(net_dev); -+ /* Make the user aware, without cluttering the boot log */ -+ dev_dbg_once(dev, " device(s) have all-zero hwaddr, replaced with random\n"); -+ err = dpni_set_primary_mac_addr(priv->mc_io, 0, -+ priv->mc_token, net_dev->dev_addr); ++ dev_dbg_once(dev, "device(s) have all-zero hwaddr, replaced with random\n"); ++ ++ err = dpni_set_primary_mac_addr(priv->mc_io, 0, priv->mc_token, ++ net_dev->dev_addr); + if (err) { -+ dev_err(dev, -+ "dpni_set_primary_mac_addr() failed (%d)\n", err); ++ dev_err(dev, "dpni_set_primary_mac_addr() failed\n"); + return err; + } ++ + /* Override NET_ADDR_RANDOM set by eth_hw_addr_random(); for all + * practical purposes, this will be our "permanent" mac address, + * at least until the next reboot. This move will also permit + * register_netdevice() to properly fill up net_dev->perm_addr. + */ + net_dev->addr_assign_type = NET_ADDR_PERM; -+ /* If DPMAC address is non-zero, use that one */ + } else { + /* NET_ADDR_PERM is default, all we have to do is + * fill in the device addr. @@ -3917,41 +5633,57 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + memcpy(net_dev->dev_addr, dpni_mac_addr, net_dev->addr_len); + } + -+ /* Explicitly add the broadcast address to the MAC filtering table; -+ * the MC won't do that for us. -+ */ ++ return 0; ++} ++ ++static int netdev_init(struct net_device *net_dev) ++{ ++ struct device *dev = net_dev->dev.parent; ++ struct dpaa2_eth_priv *priv = netdev_priv(net_dev); ++ u8 bcast_addr[ETH_ALEN]; ++ u8 num_queues; ++ int err; ++ ++ net_dev->netdev_ops = &dpaa2_eth_ops; ++ ++ err = set_mac_addr(priv); ++ if (err) ++ return err; ++ ++ /* Explicitly add the broadcast address to the MAC filtering table */ + eth_broadcast_addr(bcast_addr); + err = dpni_add_mac_addr(priv->mc_io, 0, priv->mc_token, bcast_addr); + if (err) { -+ dev_warn(dev, "dpni_add_mac_addr() failed (%d)\n", err); -+ /* Won't return an error; at least, we'd have egress traffic */ ++ dev_err(dev, "dpni_add_mac_addr() failed\n"); ++ return err; + } + -+ /* Reserve enough space to align buffer as per hardware requirement; -+ * NOTE: priv->tx_data_offset MUST be initialized at this point. -+ */ -+ net_dev->needed_headroom = DPAA2_ETH_NEEDED_HEADROOM(priv); -+ -+ /* Set MTU limits */ -+ net_dev->min_mtu = 68; ++ /* Set MTU upper limit; lower limit is default (68B) */ + net_dev->max_mtu = DPAA2_ETH_MAX_MTU; ++ err = dpni_set_max_frame_length(priv->mc_io, 0, priv->mc_token, ++ (u16)DPAA2_ETH_MFL); ++ if (err) { ++ dev_err(dev, "dpni_set_max_frame_length() failed\n"); ++ return err; ++ } + -+ /* Required headroom for Rx skbs, to avoid reallocation on -+ * forwarding path. -+ */ -+ rx_req_headroom = LL_RESERVED_SPACE(net_dev) - ETH_HLEN; -+ rx_headroom = ALIGN(DPAA2_ETH_RX_HWA_SIZE + DPAA2_ETH_SWA_SIZE + -+ DPAA2_ETH_RX_HEAD_ROOM, priv->rx_buf_align); -+ if (rx_req_headroom > rx_headroom) -+ dev_info_once(dev, -+ "Required headroom (%d) greater than available (%d).\n" -+ "This will impact performance due to reallocations.\n", -+ rx_req_headroom, rx_headroom); ++ /* Set actual number of queues in the net device */ ++ num_queues = dpaa2_eth_queue_count(priv); ++ err = netif_set_real_num_tx_queues(net_dev, num_queues); ++ if (err) { ++ dev_err(dev, "netif_set_real_num_tx_queues() failed\n"); ++ return err; ++ } ++ err = netif_set_real_num_rx_queues(net_dev, num_queues); ++ if (err) { ++ dev_err(dev, "netif_set_real_num_rx_queues() failed\n"); ++ return err; ++ } + + /* Our .ndo_init will be called herein */ + err = register_netdev(net_dev); + if (err < 0) { -+ dev_err(dev, "register_netdev() failed (%d)\n", err); ++ dev_err(dev, "register_netdev() failed\n"); + return err; + } + @@ -3974,14 +5706,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return 0; +} + -+static irqreturn_t dpni_irq0_handler(int irq_num, void *arg) -+{ -+ return IRQ_WAKE_THREAD; -+} -+ +static irqreturn_t dpni_irq0_handler_thread(int irq_num, void *arg) +{ -+ u32 status = 0, clear = 0; ++ u32 status = ~0; + struct device *dev = (struct device *)arg; + struct fsl_mc_device *dpni_dev = to_fsl_mc_device(dev); + struct net_device *net_dev = dev_get_drvdata(dev); @@ -3990,19 +5717,13 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + err = dpni_get_irq_status(dpni_dev->mc_io, 0, dpni_dev->mc_handle, + DPNI_IRQ_INDEX, &status); + if (unlikely(err)) { -+ netdev_err(net_dev, "Can't get irq status (err %d)", err); -+ clear = 0xffffffff; -+ goto out; ++ netdev_err(net_dev, "Can't get irq status (err %d)\n", err); ++ return IRQ_HANDLED; + } + -+ if (status & DPNI_IRQ_EVENT_LINK_CHANGED) { -+ clear |= DPNI_IRQ_EVENT_LINK_CHANGED; ++ if (status & DPNI_IRQ_EVENT_LINK_CHANGED) + link_state_update(netdev_priv(net_dev)); -+ } + -+out: -+ dpni_clear_irq_status(dpni_dev->mc_io, 0, dpni_dev->mc_handle, -+ DPNI_IRQ_INDEX, clear); + return IRQ_HANDLED; +} + @@ -4019,26 +5740,25 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + irq = ls_dev->irqs[0]; + err = devm_request_threaded_irq(&ls_dev->dev, irq->msi_desc->irq, -+ dpni_irq0_handler, -+ dpni_irq0_handler_thread, ++ NULL, dpni_irq0_handler_thread, + IRQF_NO_SUSPEND | IRQF_ONESHOT, + dev_name(&ls_dev->dev), &ls_dev->dev); + if (err < 0) { -+ dev_err(&ls_dev->dev, "devm_request_threaded_irq(): %d", err); ++ dev_err(&ls_dev->dev, "devm_request_threaded_irq(): %d\n", err); + goto free_mc_irq; + } + + err = dpni_set_irq_mask(ls_dev->mc_io, 0, ls_dev->mc_handle, + DPNI_IRQ_INDEX, DPNI_IRQ_EVENT_LINK_CHANGED); + if (err < 0) { -+ dev_err(&ls_dev->dev, "dpni_set_irq_mask(): %d", err); ++ dev_err(&ls_dev->dev, "dpni_set_irq_mask(): %d\n", err); + goto free_irq; + } + + err = dpni_set_irq_enable(ls_dev->mc_io, 0, ls_dev->mc_handle, + DPNI_IRQ_INDEX, 1); + if (err < 0) { -+ dev_err(&ls_dev->dev, "dpni_set_irq_enable(): %d", err); ++ dev_err(&ls_dev->dev, "dpni_set_irq_enable(): %d\n", err); + goto free_irq; + } + @@ -4095,7 +5815,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +{ + int err, items; + struct dpaa2_eth_priv *priv = netdev_priv(to_net_dev(dev)); -+ struct dpni_tx_shaping_cfg scfg; ++ struct dpni_tx_shaping_cfg scfg, ercfg = { 0 }; + + items = sscanf(buf, "%u %hu", &scfg.rate_limit, &scfg.max_burst_size); + if (items != 2) { @@ -4109,7 +5829,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return -EINVAL; + } + -+ err = dpni_set_tx_shaping(priv->mc_io, 0, priv->mc_token, &scfg); ++ err = dpni_set_tx_shaping(priv->mc_io, 0, priv->mc_token, &scfg, ++ &ercfg, 0); + if (err) { + dev_err(dev, "dpni_set_tx_shaping() failed\n"); + return -EPERM; @@ -4120,79 +5841,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return count; +} + -+static ssize_t dpaa2_eth_show_txconf_cpumask(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct dpaa2_eth_priv *priv = netdev_priv(to_net_dev(dev)); -+ -+ return cpumap_print_to_pagebuf(1, buf, &priv->txconf_cpumask); -+} -+ -+static ssize_t dpaa2_eth_write_txconf_cpumask(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, -+ size_t count) -+{ -+ struct dpaa2_eth_priv *priv = netdev_priv(to_net_dev(dev)); -+ struct dpaa2_eth_fq *fq; -+ bool running = netif_running(priv->net_dev); -+ int i, err; -+ -+ err = cpulist_parse(buf, &priv->txconf_cpumask); -+ if (err) -+ return err; -+ -+ /* Only accept CPUs that have an affine DPIO */ -+ if (!cpumask_subset(&priv->txconf_cpumask, &priv->dpio_cpumask)) { -+ netdev_info(priv->net_dev, -+ "cpumask must be a subset of 0x%lx\n", -+ *cpumask_bits(&priv->dpio_cpumask)); -+ cpumask_and(&priv->txconf_cpumask, &priv->dpio_cpumask, -+ &priv->txconf_cpumask); -+ } -+ -+ /* Rewiring the TxConf FQs requires interface shutdown. -+ */ -+ if (running) { -+ err = dpaa2_eth_stop(priv->net_dev); -+ if (err) -+ return -ENODEV; -+ } -+ -+ /* Set the new TxConf FQ affinities */ -+ set_fq_affinity(priv); -+ -+ /* dpaa2_eth_open() below will *stop* the Tx queues until an explicit -+ * link up notification is received. Give the polling thread enough time -+ * to detect the link state change, or else we'll end up with the -+ * transmission side forever shut down. -+ */ -+ if (priv->do_link_poll) -+ msleep(2 * DPAA2_ETH_LINK_STATE_REFRESH); -+ -+ for (i = 0; i < priv->num_fqs; i++) { -+ fq = &priv->fq[i]; -+ if (fq->type != DPAA2_TX_CONF_FQ) -+ continue; -+ setup_tx_flow(priv, fq); -+ } -+ -+ if (running) { -+ err = dpaa2_eth_open(priv->net_dev); -+ if (err) -+ return -ENODEV; -+ } -+ -+ return count; -+} -+ +static struct device_attribute dpaa2_eth_attrs[] = { -+ __ATTR(txconf_cpumask, -+ 0600, -+ dpaa2_eth_show_txconf_cpumask, -+ dpaa2_eth_write_txconf_cpumask), -+ + __ATTR(tx_shaping, + 0600, + dpaa2_eth_show_tx_shaping, @@ -4234,7 +5883,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct dpni_link_state state; + int err, i; + -+ pfc->pfc_cap = dpaa2_eth_tc_count(priv); ++ priv->pfc.pfc_cap = dpaa2_eth_tc_count(priv); + + err = dpni_get_link_state(priv->mc_io, 0, priv->mc_token, &state); + if (err) { @@ -4261,9 +5910,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + priv->pfc.pfc_en |= 1 << i; + } + -+ pfc->pfc_en = priv->pfc.pfc_en; -+ pfc->mbc = priv->pfc.mbc; -+ pfc->delay = priv->pfc.delay; ++ memcpy(pfc, &priv->pfc, sizeof(priv->pfc)); + + return 0; +} @@ -4275,8 +5922,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct dpkg_profile_cfg kg_cfg = {0}; + struct dpni_qos_tbl_cfg qos_cfg = {0}; + struct dpni_rule_cfg key_params; -+ u8 *params_iova; -+ __be16 key, mask = cpu_to_be16(VLAN_PRIO_MASK); ++ u8 *params_iova, *key, *mask = NULL; ++ /* We only need the trailing 16 bits, without the TPID */ ++ u8 key_size = VLAN_HLEN / 2; + int err = 0, i, j = 0; + + if (priv->vlan_clsf_set) @@ -4318,49 +5966,79 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + goto out_free; + } + -+ key_params.key_size = sizeof(key); ++ key_params.key_size = key_size; + + if (dpaa2_eth_fs_mask_enabled(priv)) { -+ key_params.mask_iova = dma_map_single(dev, &mask, sizeof(mask), ++ mask = kzalloc(key_size, GFP_KERNEL); ++ if (!mask) ++ goto out_free; ++ ++ *mask = cpu_to_be16(VLAN_PRIO_MASK); ++ ++ key_params.mask_iova = dma_map_single(dev, mask, key_size, + DMA_TO_DEVICE); + if (dma_mapping_error(dev, key_params.mask_iova)) { + dev_err(dev, "DMA mapping failed %s\n", __func__); + err = -ENOMEM; -+ goto out_free; ++ goto out_free_mask; + } + } else { + key_params.mask_iova = 0; + } + -+ key_params.key_iova = dma_map_single(dev, &key, sizeof(key), ++ key = kzalloc(key_size, GFP_KERNEL); ++ if (!key) ++ goto out_cleanup_mask; ++ ++ key_params.key_iova = dma_map_single(dev, key, key_size, + DMA_TO_DEVICE); + if (dma_mapping_error(dev, key_params.key_iova)) { + dev_err(dev, "%s: DMA mapping failed\n", __func__); + err = -ENOMEM; -+ goto out_unmap_mask; ++ goto out_free_key; + } + + for (i = 0; i < dpaa2_eth_tc_count(priv); i++) { -+ key = cpu_to_be16(i << VLAN_PRIO_SHIFT); ++ *key = cpu_to_be16(i << VLAN_PRIO_SHIFT); ++ + dma_sync_single_for_device(dev, key_params.key_iova, -+ sizeof(key), DMA_TO_DEVICE); ++ key_size, DMA_TO_DEVICE); + + err = dpni_add_qos_entry(priv->mc_io, 0, priv->mc_token, + &key_params, i, j++); + if (err) { + dev_err(dev, "dpni_add_qos_entry failed: %d\n", err); -+ goto out_unmap; ++ goto out_remove; + } + } + + priv->vlan_clsf_set = true; ++ dev_dbg(dev, "Vlan PCP QoS classification set\n"); ++ goto out_cleanup; + -+out_unmap: -+ dma_unmap_single(dev, key_params.key_iova, sizeof(key), DMA_TO_DEVICE); -+out_unmap_mask: ++out_remove: ++ for (j = 0; j < i; j++) { ++ *key = cpu_to_be16(j << VLAN_PRIO_SHIFT); ++ ++ dma_sync_single_for_device(dev, key_params.key_iova, key_size, ++ DMA_TO_DEVICE); ++ ++ err = dpni_remove_qos_entry(priv->mc_io, 0, priv->mc_token, ++ &key_params); ++ if (err) ++ dev_err(dev, "dpni_remove_qos_entry failed: %d\n", err); ++ } ++ ++out_cleanup: ++ dma_unmap_single(dev, key_params.key_iova, key_size, DMA_TO_DEVICE); ++out_free_key: ++ kfree(key); ++out_cleanup_mask: + if (key_params.mask_iova) -+ dma_unmap_single(dev, key_params.mask_iova, sizeof(mask), ++ dma_unmap_single(dev, key_params.mask_iova, key_size, + DMA_TO_DEVICE); ++out_free_mask: ++ kfree(mask); +out_free: + kfree(params_iova); + return err; @@ -4373,8 +6051,17 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct dpni_congestion_notification_cfg notification_cfg = {0}; + struct dpni_link_state state = {0}; + struct dpni_link_cfg cfg = {0}; ++ struct ieee_pfc old_pfc; + int err = 0, i; + ++ if (dpaa2_eth_tc_count(priv) == 1) { ++ netdev_dbg(net_dev, "DPNI has 1 TC, PFC configuration N/A\n"); ++ return 0; ++ } ++ ++ /* Zero out pfc_enabled prios greater than tc_count */ ++ pfc->pfc_en &= (1 << dpaa2_eth_tc_count(priv)) - 1; ++ + if (priv->pfc.pfc_en == pfc->pfc_en) + /* Same enabled mask, nothing to be done */ + return 0; @@ -4402,11 +6089,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return err; + } + ++ memcpy(&old_pfc, &priv->pfc, sizeof(priv->pfc)); + memcpy(&priv->pfc, pfc, sizeof(priv->pfc)); + + err = set_rx_taildrop(priv); + if (err) -+ return err; ++ goto out_restore_config; + + /* configure congestion notifications */ + notification_cfg.notification_mode = DPNI_CONG_OPT_FLOW_CONTROL; @@ -4430,11 +6118,19 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + if (err) { + netdev_err(net_dev, "Error %d setting congestion notif", + err); -+ return err; ++ goto out_restore_config; + } ++ ++ netdev_dbg(net_dev, "%s congestion notifications for tc %d\n", ++ (notification_cfg.threshold_entry ? ++ "Enabled" : "Disabled"), i); + } + + return 0; ++ ++out_restore_config: ++ memcpy(&priv->pfc, &old_pfc, sizeof(priv->pfc)); ++ return err; +} + +static u8 dpaa2_eth_dcbnl_getdcbx(struct net_device *net_dev) @@ -4461,7 +6157,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + *cap = true; + break; + case DCB_CAP_ATTR_PFC_TCS: -+ *cap = 1 << dpaa2_eth_tc_count(priv); ++ /* bitmap where each bit represents a number of traffic ++ * classes the device can be configured to use for Priority ++ * Flow Control ++ */ ++ *cap = 1 << (dpaa2_eth_tc_count(priv) - 1); + break; + case DCB_CAP_ATTR_DCBX: + *cap = priv->dcbx_mode; @@ -4511,8 +6211,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + err = fsl_mc_portal_allocate(dpni_dev, FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, + &priv->mc_io); + if (err) { -+ dev_dbg(dev, "MC portal allocation failed\n"); -+ err = -EPROBE_DEFER; ++ if (err == -ENXIO) ++ err = -EPROBE_DEFER; ++ else ++ dev_err(dev, "MC portal allocation failed\n"); + goto err_portal_alloc; + } + @@ -4522,11 +6224,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + goto err_dpni_setup; + + err = setup_dpio(priv); -+ if (err) { -+ dev_info(dev, "Defer probing as no DPIO available\n"); -+ err = -EPROBE_DEFER; ++ if (err) + goto err_dpio_setup; -+ } + + setup_fqs(priv); + @@ -4552,15 +6251,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + goto err_alloc_percpu_extras; + } + -+ snprintf(net_dev->name, IFNAMSIZ, "ni%d", dpni_dev->obj_desc.id); -+ if (!dev_valid_name(net_dev->name)) { -+ dev_warn(&net_dev->dev, -+ "netdevice name \"%s\" cannot be used, reverting to default..\n", -+ net_dev->name); -+ dev_alloc_name(net_dev, "eth%d"); -+ dev_warn(&net_dev->dev, "using name \"%s\"\n", net_dev->name); -+ } -+ + err = netdev_init(net_dev); + if (err) + goto err_netdev_init; @@ -4651,12 +6341,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#endif + dpaa2_eth_sysfs_remove(&net_dev->dev); + ++ unregister_netdev(net_dev); ++ + disable_ch_napi(priv); + del_ch_napi(priv); + -+ unregister_netdev(net_dev); -+ dev_info(net_dev->dev.parent, "Removed interface %s\n", net_dev->name); -+ + if (priv->do_link_poll) + kthread_stop(priv->poll_thread); + else @@ -4674,6 +6363,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + dev_set_drvdata(dev, NULL); + free_netdev(net_dev); + ++ dev_dbg(net_dev->dev.parent, "Removed interface %s\n", net_dev->name); ++ + return 0; +} + @@ -4702,26 +6393,36 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + dpaa2_eth_dbg_init(); + err = fsl_mc_driver_register(&dpaa2_eth_driver); -+ if (err) { -+ dpaa2_eth_dbg_exit(); -+ return err; -+ } ++ if (err) ++ goto out_debugfs_err; ++ ++ err = dpaa2_ceetm_register(); ++ if (err) ++ goto out_ceetm_err; + + return 0; ++ ++out_ceetm_err: ++ fsl_mc_driver_unregister(&dpaa2_eth_driver); ++out_debugfs_err: ++ dpaa2_eth_dbg_exit(); ++ return err; +} + +static void __exit dpaa2_eth_driver_exit(void) +{ -+ dpaa2_eth_dbg_exit(); ++ dpaa2_ceetm_unregister(); + fsl_mc_driver_unregister(&dpaa2_eth_driver); ++ dpaa2_eth_dbg_exit(); +} + +module_init(dpaa2_eth_driver_init); +module_exit(dpaa2_eth_driver_exit); --- /dev/null +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h -@@ -0,0 +1,499 @@ -+/* Copyright 2014-2015 Freescale Semiconductor Inc. +@@ -0,0 +1,601 @@ ++/* Copyright 2014-2016 Freescale Semiconductor Inc. ++ * Copyright 2016 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: @@ -4755,16 +6456,20 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#ifndef __DPAA2_ETH_H +#define __DPAA2_ETH_H + -+#include <linux/atomic.h> +#include <linux/dcbnl.h> +#include <linux/netdevice.h> +#include <linux/if_vlan.h> ++ +#include "../../fsl-mc/include/dpaa2-io.h" ++#include "../../fsl-mc/include/dpaa2-fd.h" +#include "dpni.h" -+#include "net.h" ++#include "dpni-cmd.h" + ++#include "dpaa2-eth-trace.h" +#include "dpaa2-eth-debugfs.h" + ++#define DPAA2_WRIOP_VERSION(x, y, z) ((x) << 10 | (y) << 5 | (z) << 0) ++ +#define DPAA2_ETH_STORE_SIZE 16 + +/* We set a max threshold for how many Tx confirmations we should process @@ -4805,58 +6510,61 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * to accommodate the buffer refill delay. + */ +#define DPAA2_ETH_MAX_FRAMES_PER_QUEUE (DPAA2_ETH_TAILDROP_THRESH / 64) -+#define DPAA2_ETH_NUM_BUFS_TD (DPAA2_ETH_MAX_FRAMES_PER_QUEUE + 256) -+#define DPAA2_ETH_REFILL_THRESH_TD \ -+ (DPAA2_ETH_NUM_BUFS_TD - DPAA2_ETH_BUFS_PER_CMD) ++#define DPAA2_ETH_NUM_BUFS_PER_CH (DPAA2_ETH_MAX_FRAMES_PER_QUEUE + 256) ++#define DPAA2_ETH_REFILL_THRESH(priv) \ ++ ((priv)->max_bufs_per_ch - DPAA2_ETH_BUFS_PER_CMD) + -+/* Buffer quota per queue to use when flow control is active. */ ++/* Global buffer quota in case flow control is enabled */ +#define DPAA2_ETH_NUM_BUFS_FC 256 + -+/* Hardware requires alignment for ingress/egress buffer addresses -+ * and ingress buffer lengths. -+ */ -+#define DPAA2_ETH_RX_BUF_SIZE 2048 ++/* Hardware requires alignment for ingress/egress buffer addresses */ +#define DPAA2_ETH_TX_BUF_ALIGN 64 ++ ++/* Due to a limitation in WRIOP 1.0.0, the RX buffer data must be aligned ++ * to 256B. For newer revisions, the requirement is only for 64B alignment ++ */ ++#define DPAA2_ETH_RX_BUF_ALIGN_REV1 256 +#define DPAA2_ETH_RX_BUF_ALIGN 64 -+#define DPAA2_ETH_RX_BUF_ALIGN_V1 256 -+#define DPAA2_ETH_NEEDED_HEADROOM(p_priv) \ -+ ((p_priv)->tx_data_offset + DPAA2_ETH_TX_BUF_ALIGN - HH_DATA_MOD) + -+/* rx_extra_head prevents reallocations in L3 processing. */ ++#define DPAA2_ETH_RX_BUF_SIZE 2048 +#define DPAA2_ETH_SKB_SIZE \ -+ (DPAA2_ETH_RX_BUF_SIZE + \ -+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info))) -+ -+/* Hardware only sees DPAA2_ETH_RX_BUF_SIZE, but we need to allocate ingress -+ * buffers large enough to allow building an skb around them and also account -+ * for alignment restrictions. -+ */ -+#define DPAA2_ETH_BUF_RAW_SIZE(p_priv) \ -+ (DPAA2_ETH_SKB_SIZE + \ -+ (p_priv)->rx_buf_align) ++ (DPAA2_ETH_RX_BUF_SIZE + SKB_DATA_ALIGN(sizeof(struct skb_shared_info))) + +/* PTP nominal frequency 1GHz */ +#define DPAA2_PTP_NOMINAL_FREQ_PERIOD_NS 1 + ++/* Hardware annotation area in RX/TX buffers */ ++#define DPAA2_ETH_RX_HWA_SIZE 64 ++#define DPAA2_ETH_TX_HWA_SIZE 128 ++ +/* We are accommodating a skb backpointer and some S/G info + * in the frame's software annotation. The hardware + * options are either 0 or 64, so we choose the latter. + */ +#define DPAA2_ETH_SWA_SIZE 64 + -+/* Extra headroom space requested to hardware, in order to make sure there's -+ * no realloc'ing in forwarding scenarios ++/* We store different information in the software annotation area of a Tx frame ++ * based on what type of frame it is + */ -+#define DPAA2_ETH_RX_HEAD_ROOM \ -+ (DPAA2_ETH_TX_HWA_SIZE - DPAA2_ETH_RX_HWA_SIZE + \ -+ DPAA2_ETH_TX_BUF_ALIGN) ++enum dpaa2_eth_swa_type { ++ DPAA2_ETH_SWA_SINGLE, ++ DPAA2_ETH_SWA_SG, ++}; + +/* Must keep this struct smaller than DPAA2_ETH_SWA_SIZE */ +struct dpaa2_eth_swa { -+ struct sk_buff *skb; -+ struct scatterlist *scl; -+ int num_sg; -+ int num_dma_bufs; ++ enum dpaa2_eth_swa_type type; ++ union { ++ struct { ++ struct sk_buff *skb; ++ } single; ++ struct { ++ struct sk_buff *skb; ++ struct scatterlist *scl; ++ int num_sg; ++ int sgt_size; ++ } sg; ++ }; +}; + +/* Annotation valid bits in FD FRC */ @@ -4876,22 +6584,16 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +/* Annotation bits in FD CTRL */ +#define DPAA2_FD_CTRL_ASAL 0x00020000 /* ASAL = 128 */ + -+/* Size of hardware annotation area based on the current buffer layout -+ * configuration -+ */ -+#define DPAA2_ETH_RX_HWA_SIZE 64 -+#define DPAA2_ETH_TX_HWA_SIZE 128 -+ +/* Frame annotation status */ +struct dpaa2_fas { + u8 reserved; + u8 ppid; + __le16 ifpid; + __le32 status; -+} __packed; ++}; + +/* Frame annotation status word is located in the first 8 bytes -+ * of the buffer's hardware annotation area ++ * of the buffer's hardware annoatation area + */ +#define DPAA2_FAS_OFFSET 0 +#define DPAA2_FAS_SIZE (sizeof(struct dpaa2_fas)) @@ -4910,21 +6612,31 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; + +#define DPAA2_FAEAD_A2V 0x20000000 ++#define DPAA2_FAEAD_A4V 0x08000000 +#define DPAA2_FAEAD_UPDV 0x00001000 ++#define DPAA2_FAEAD_EBDDV 0x00002000 +#define DPAA2_FAEAD_UPD 0x00000010 + -+/* accessors for the hardware annotation fields that we use */ -+#define dpaa2_eth_get_hwa(buf_addr) \ -+ ((void *)(buf_addr) + DPAA2_ETH_SWA_SIZE) ++/* Accessors for the hardware annotation fields that we use */ ++static inline void *dpaa2_get_hwa(void *buf_addr, bool swa) ++{ ++ return buf_addr + (swa ? DPAA2_ETH_SWA_SIZE : 0); ++} + -+#define dpaa2_eth_get_fas(buf_addr) \ -+ (struct dpaa2_fas *)(dpaa2_eth_get_hwa(buf_addr) + DPAA2_FAS_OFFSET) ++static inline struct dpaa2_fas *dpaa2_get_fas(void *buf_addr, bool swa) ++{ ++ return dpaa2_get_hwa(buf_addr, swa) + DPAA2_FAS_OFFSET; ++} + -+#define dpaa2_eth_get_ts(buf_addr) \ -+ (u64 *)(dpaa2_eth_get_hwa(buf_addr) + DPAA2_TS_OFFSET) ++static inline u64 *dpaa2_get_ts(void *buf_addr, bool swa) ++{ ++ return dpaa2_get_hwa(buf_addr, swa) + DPAA2_TS_OFFSET; ++} + -+#define dpaa2_eth_get_faead(buf_addr) \ -+ (struct dpaa2_faead *)(dpaa2_eth_get_hwa(buf_addr) + DPAA2_FAEAD_OFFSET) ++static inline struct dpaa2_faead *dpaa2_get_faead(void *buf_addr, bool swa) ++{ ++ return dpaa2_get_hwa(buf_addr, swa) + DPAA2_FAEAD_OFFSET; ++} + +/* Error and status bits in the frame annotation status word */ +/* Debug frame, otherwise supposed to be discarded */ @@ -4958,24 +6670,19 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +/* L4 csum error */ +#define DPAA2_FAS_L4CE 0x00000001 +/* Possible errors on the ingress path */ -+#define DPAA2_FAS_RX_ERR_MASK ((DPAA2_FAS_KSE) | \ -+ (DPAA2_FAS_EOFHE) | \ -+ (DPAA2_FAS_MNLE) | \ -+ (DPAA2_FAS_TIDE) | \ -+ (DPAA2_FAS_PIEE) | \ -+ (DPAA2_FAS_FLE) | \ -+ (DPAA2_FAS_FPE) | \ -+ (DPAA2_FAS_PTE) | \ -+ (DPAA2_FAS_ISP) | \ -+ (DPAA2_FAS_PHE) | \ -+ (DPAA2_FAS_BLE) | \ -+ (DPAA2_FAS_L3CE) | \ -+ (DPAA2_FAS_L4CE)) -+/* Tx errors */ -+#define DPAA2_FAS_TX_ERR_MASK ((DPAA2_FAS_KSE) | \ -+ (DPAA2_FAS_EOFHE) | \ -+ (DPAA2_FAS_MNLE) | \ -+ (DPAA2_FAS_TIDE)) ++#define DPAA2_FAS_RX_ERR_MASK (DPAA2_FAS_KSE | \ ++ DPAA2_FAS_EOFHE | \ ++ DPAA2_FAS_MNLE | \ ++ DPAA2_FAS_TIDE | \ ++ DPAA2_FAS_PIEE | \ ++ DPAA2_FAS_FLE | \ ++ DPAA2_FAS_FPE | \ ++ DPAA2_FAS_PTE | \ ++ DPAA2_FAS_ISP | \ ++ DPAA2_FAS_PHE | \ ++ DPAA2_FAS_BLE | \ ++ DPAA2_FAS_L3CE | \ ++ DPAA2_FAS_L4CE) + +/* Time in milliseconds between link state updates */ +#define DPAA2_ETH_LINK_STATE_REFRESH 1000 @@ -4984,14 +6691,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * Value determined empirically, in order to minimize the number + * of frames dropped on Tx + */ -+#define DPAA2_ETH_ENQUEUE_RETRIES 10 ++#define DPAA2_ETH_ENQUEUE_RETRIES 10 + +/* Tx congestion entry & exit thresholds, in number of bytes. + * We allow a maximum of 512KB worth of frames pending processing on the Tx + * queues of an interface + */ -+#define DPAA2_ETH_TX_CONG_ENTRY_THRESH (512 * 1024) -+#define DPAA2_ETH_TX_CONG_EXIT_THRESH (DPAA2_ETH_TX_CONG_ENTRY_THRESH * 9/10) ++#define DPAA2_ETH_TX_CONG_ENTRY_THRESH (512 * 1024) ++#define DPAA2_ETH_TX_CONG_EXIT_THRESH \ ++ (DPAA2_ETH_TX_CONG_ENTRY_THRESH * 9 / 10) + +/* Driver statistics, other than those in struct rtnl_link_stats64. + * These are usually collected per-CPU and aggregated by ethtool. @@ -5001,6 +6709,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + __u64 tx_conf_bytes; + __u64 tx_sg_frames; + __u64 tx_sg_bytes; ++ __u64 tx_reallocs; + __u64 rx_sg_frames; + __u64 rx_sg_bytes; + /* Enqueues retried due to portal busy */ @@ -5027,7 +6736,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + __u64 pull_err; +}; + -+#define DPAA2_ETH_MAX_DPCONS NR_CPUS +#define DPAA2_ETH_MAX_TCS 8 + +/* Maximum number of queues associated with a DPNI */ @@ -5038,6 +6746,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + DPAA2_ETH_MAX_TX_QUEUES + \ + DPAA2_ETH_MAX_RX_ERR_QUEUES) + ++#define DPAA2_ETH_MAX_DPCONS 16 ++ +enum dpaa2_eth_fq_type { + DPAA2_RX_FQ = 0, + DPAA2_TX_CONF_FQ, @@ -5068,12 +6778,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct fsl_mc_device *dpcon; + int dpcon_id; + int ch_id; -+ int dpio_id; + struct napi_struct napi; ++ struct dpaa2_io *dpio; + struct dpaa2_io_store *store; + struct dpaa2_eth_priv *priv; + int buf_count; + struct dpaa2_eth_ch_stats stats; ++ struct bpf_prog *xdp_prog; ++ u64 rel_buf_array[DPAA2_ETH_BUFS_PER_CMD]; ++ u8 rel_buf_cnt; +}; + +struct dpaa2_eth_cls_rule { @@ -5081,60 +6794,51 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + bool in_use; +}; + -+struct dpaa2_eth_hash_fields { ++struct dpaa2_eth_dist_fields { + u64 rxnfc_field; + enum net_prot cls_prot; + int cls_field; + int offset; + int size; ++ u32 id; +}; + +/* Driver private data */ +struct dpaa2_eth_priv { + struct net_device *net_dev; -+ + /* Standard statistics */ + struct rtnl_link_stats64 __percpu *percpu_stats; + /* Extra stats, in addition to the ones known by the kernel */ + struct dpaa2_eth_drv_stats __percpu *percpu_extras; -+ struct iommu_domain *iommu_domain; -+ + bool ts_tx_en; /* Tx timestamping enabled */ + bool ts_rx_en; /* Rx timestamping enabled */ -+ + u16 tx_data_offset; -+ u16 rx_buf_align; -+ + u16 bpid; + u16 tx_qdid; -+ -+ int tx_pause_frames; -+ int num_bufs; ++ u16 rx_buf_align; ++ struct iommu_domain *iommu_domain; ++ int max_bufs_per_ch; + int refill_thresh; ++ bool has_xdp_prog; + -+ /* Tx congestion notifications are written here */ -+ void *cscn_mem; ++ void *cscn_mem; /* Tx congestion notifications are written here */ + void *cscn_unaligned; + dma_addr_t cscn_dma; + + u8 num_fqs; -+ /* Tx queues are at the beginning of the array */ + struct dpaa2_eth_fq fq[DPAA2_ETH_MAX_QUEUES]; + + u8 num_channels; + struct dpaa2_eth_channel *channel[DPAA2_ETH_MAX_DPCONS]; + -+ int dpni_id; + struct dpni_attr dpni_attrs; ++ u16 dpni_ver_major; ++ u16 dpni_ver_minor; + struct fsl_mc_device *dpbp_dev; + + struct fsl_mc_io *mc_io; -+ /* SysFS-controlled affinity mask for TxConf FQs */ -+ struct cpumask txconf_cpumask; + /* Cores which have an affine DPIO/DPCON. -+ * This is the cpu set on which Rx frames are processed; -+ * Tx confirmation frames are processed on a subset of this, -+ * depending on user settings. ++ * This is the cpu set on which Rx and Tx conf frames are processed + */ + struct cpumask dpio_cpumask; + @@ -5144,25 +6848,52 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + bool do_link_poll; + struct task_struct *poll_thread; + -+ struct dpaa2_eth_hash_fields *hash_fields; -+ u8 num_hash_fields; ++ /* Rx distribution (hash and flow steering) header fields ++ * supported by the driver ++ */ ++ struct dpaa2_eth_dist_fields *dist_fields; ++ u8 num_dist_fields; + /* enabled ethtool hashing bits */ -+ u64 rx_flow_hash; -+ ++ u64 rx_hash_fields; +#ifdef CONFIG_FSL_DPAA2_ETH_DEBUGFS + struct dpaa2_debugfs dbg; +#endif -+ + /* array of classification rules */ + struct dpaa2_eth_cls_rule *cls_rule; -+ + struct dpni_tx_shaping_cfg shaping_cfg; + + u8 dcbx_mode; + struct ieee_pfc pfc; + bool vlan_clsf_set; ++ bool tx_pause_frames; ++ ++ bool ceetm_en; ++}; ++ ++enum dpaa2_eth_rx_dist { ++ DPAA2_ETH_RX_DIST_HASH, ++ DPAA2_ETH_RX_DIST_FS, ++ DPAA2_ETH_RX_DIST_LEGACY +}; + ++/* Supported Rx distribution field ids */ ++#define DPAA2_ETH_DIST_ETHSRC BIT(0) ++#define DPAA2_ETH_DIST_ETHDST BIT(1) ++#define DPAA2_ETH_DIST_ETHTYPE BIT(2) ++#define DPAA2_ETH_DIST_VLAN BIT(3) ++#define DPAA2_ETH_DIST_IPSRC BIT(4) ++#define DPAA2_ETH_DIST_IPDST BIT(5) ++#define DPAA2_ETH_DIST_IPPROTO BIT(6) ++#define DPAA2_ETH_DIST_L4SRC BIT(7) ++#define DPAA2_ETH_DIST_L4DST BIT(8) ++#define DPAA2_ETH_DIST_ALL (~0U) ++ ++/* Default Rx hash key */ ++#define DPAA2_ETH_DIST_DEFAULT_HASH \ ++ (DPAA2_ETH_DIST_IPPROTO | \ ++ DPAA2_ETH_DIST_IPSRC | DPAA2_ETH_DIST_IPDST | \ ++ DPAA2_ETH_DIST_L4SRC | DPAA2_ETH_DIST_L4DST) ++ +#define dpaa2_eth_hash_enabled(priv) \ + ((priv)->dpni_attrs.num_queues > 1) + @@ -5175,12 +6906,74 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#define dpaa2_eth_fs_count(priv) \ + ((priv)->dpni_attrs.fs_entries) + -+/* size of DMA memory used to pass configuration to classifier, in bytes */ ++/* Required by struct dpni_rx_tc_dist_cfg::key_cfg_iova */ +#define DPAA2_CLASSIFIER_DMA_SIZE 256 + +extern const struct ethtool_ops dpaa2_ethtool_ops; +extern const char dpaa2_eth_drv_version[]; + ++static inline int dpaa2_eth_cmp_dpni_ver(struct dpaa2_eth_priv *priv, ++ u16 ver_major, u16 ver_minor) ++{ ++ if (priv->dpni_ver_major == ver_major) ++ return priv->dpni_ver_minor - ver_minor; ++ return priv->dpni_ver_major - ver_major; ++} ++ ++#define DPNI_DIST_KEY_VER_MAJOR 7 ++#define DPNI_DIST_KEY_VER_MINOR 5 ++ ++static inline bool dpaa2_eth_has_legacy_dist(struct dpaa2_eth_priv *priv) ++{ ++ return (dpaa2_eth_cmp_dpni_ver(priv, DPNI_DIST_KEY_VER_MAJOR, ++ DPNI_DIST_KEY_VER_MINOR) < 0); ++} ++ ++/* Hardware only sees DPAA2_ETH_RX_BUF_SIZE, but the skb built around ++ * the buffer also needs space for its shared info struct, and we need ++ * to allocate enough to accommodate hardware alignment restrictions ++ */ ++static inline unsigned int dpaa2_eth_buf_raw_size(struct dpaa2_eth_priv *priv) ++{ ++ return DPAA2_ETH_SKB_SIZE + priv->rx_buf_align; ++} ++ ++/* Total headroom needed by the hardware in Tx frame buffers */ ++static inline unsigned int ++dpaa2_eth_needed_headroom(struct dpaa2_eth_priv *priv, struct sk_buff *skb) ++{ ++ unsigned int headroom = DPAA2_ETH_SWA_SIZE; ++ ++ /* If we don't have an skb (e.g. XDP buffer), we only need space for ++ * the software annotation area ++ */ ++ if (!skb) ++ return headroom; ++ ++ /* For non-linear skbs we have no headroom requirement, as we build a ++ * SG frame with a newly allocated SGT buffer ++ */ ++ if (skb_is_nonlinear(skb)) ++ return 0; ++ ++ /* If we have Tx timestamping, need 128B hardware annotation */ ++ if (priv->ts_tx_en && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) ++ headroom += DPAA2_ETH_TX_HWA_SIZE; ++ ++ return headroom; ++} ++ ++/* Extra headroom space requested to hardware, in order to make sure there's ++ * no realloc'ing in forwarding scenarios. We need to reserve enough space ++ * such that we can accommodate the maximum required Tx offset and alignment ++ * in the ingress frame buffer ++ */ ++static inline unsigned int dpaa2_eth_rx_headroom(struct dpaa2_eth_priv *priv) ++{ ++ return priv->tx_data_offset + DPAA2_ETH_TX_BUF_ALIGN - ++ DPAA2_ETH_RX_HWA_SIZE; ++} ++ +static inline int dpaa2_eth_queue_count(struct dpaa2_eth_priv *priv) +{ + return priv->dpni_attrs.num_queues; @@ -5216,14 +7009,24 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return DPAA2_ETH_TD_QUEUE; +} + ++static inline int dpaa2_eth_ch_count(struct dpaa2_eth_priv *priv) ++{ ++ return 1; ++} ++ +void check_cls_support(struct dpaa2_eth_priv *priv); + +int set_rx_taildrop(struct dpaa2_eth_priv *priv); ++ ++int dpaa2_eth_set_dist_key(struct dpaa2_eth_priv *priv, ++ enum dpaa2_eth_rx_dist type, u32 key_fields); ++ +#endif /* __DPAA2_H */ --- /dev/null +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c -@@ -0,0 +1,864 @@ -+/* Copyright 2014-2015 Freescale Semiconductor Inc. +@@ -0,0 +1,878 @@ ++/* Copyright 2014-2016 Freescale Semiconductor Inc. ++ * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: @@ -5257,49 +7060,44 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#include "dpni.h" /* DPNI_LINK_OPT_* */ +#include "dpaa2-eth.h" + -+/* To be kept in sync with dpni_statistics */ ++/* To be kept in sync with DPNI statistics */ +static char dpaa2_ethtool_stats[][ETH_GSTRING_LEN] = { -+ "rx frames", -+ "rx bytes", -+ "rx mcast frames", -+ "rx mcast bytes", -+ "rx bcast frames", -+ "rx bcast bytes", -+ "tx frames", -+ "tx bytes", -+ "tx mcast frames", -+ "tx mcast bytes", -+ "tx bcast frames", -+ "tx bcast bytes", -+ "rx filtered frames", -+ "rx discarded frames", -+ "rx nobuffer discards", -+ "tx discarded frames", -+ "tx confirmed frames", ++ "[hw] rx frames", ++ "[hw] rx bytes", ++ "[hw] rx mcast frames", ++ "[hw] rx mcast bytes", ++ "[hw] rx bcast frames", ++ "[hw] rx bcast bytes", ++ "[hw] tx frames", ++ "[hw] tx bytes", ++ "[hw] tx mcast frames", ++ "[hw] tx mcast bytes", ++ "[hw] tx bcast frames", ++ "[hw] tx bcast bytes", ++ "[hw] rx filtered frames", ++ "[hw] rx discarded frames", ++ "[hw] rx nobuffer discards", ++ "[hw] tx discarded frames", ++ "[hw] tx confirmed frames", +}; + +#define DPAA2_ETH_NUM_STATS ARRAY_SIZE(dpaa2_ethtool_stats) + -+/* To be kept in sync with 'struct dpaa2_eth_drv_stats' */ +static char dpaa2_ethtool_extras[][ETH_GSTRING_LEN] = { + /* per-cpu stats */ -+ -+ "tx conf frames", -+ "tx conf bytes", -+ "tx sg frames", -+ "tx sg bytes", -+ "rx sg frames", -+ "rx sg bytes", -+ /* how many times we had to retry the enqueue command */ -+ "enqueue portal busy", -+ ++ "[drv] tx conf frames", ++ "[drv] tx conf bytes", ++ "[drv] tx sg frames", ++ "[drv] tx sg bytes", ++ "[drv] tx realloc frames", ++ "[drv] rx sg frames", ++ "[drv] rx sg bytes", ++ "[drv] enqueue portal busy", + /* Channel stats */ -+ /* How many times we had to retry the volatile dequeue command */ -+ "dequeue portal busy", -+ "channel pull errors", -+ /* Number of notifications received */ -+ "cdan", -+ "tx congestion state", ++ "[drv] dequeue portal busy", ++ "[drv] channel pull errors", ++ "[drv] cdan", ++ "[drv] tx congestion state", +#ifdef CONFIG_FSL_QBMAN_DEBUG + /* FQ stats */ + "rx pending frames", @@ -5315,16 +7113,22 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +static void dpaa2_eth_get_drvinfo(struct net_device *net_dev, + struct ethtool_drvinfo *drvinfo) +{ ++ struct dpaa2_eth_priv *priv = netdev_priv(net_dev); ++ + strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver)); + strlcpy(drvinfo->version, dpaa2_eth_drv_version, + sizeof(drvinfo->version)); -+ strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); ++ ++ snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), ++ "%u.%u", priv->dpni_ver_major, priv->dpni_ver_minor); ++ + strlcpy(drvinfo->bus_info, dev_name(net_dev->dev.parent->parent), + sizeof(drvinfo->bus_info)); +} + -+static int dpaa2_eth_get_settings(struct net_device *net_dev, -+ struct ethtool_cmd *cmd) ++static int ++dpaa2_eth_get_link_ksettings(struct net_device *net_dev, ++ struct ethtool_link_ksettings *link_settings) +{ + struct dpni_link_state state = {0}; + int err = 0; @@ -5332,7 +7136,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + err = dpni_get_link_state(priv->mc_io, 0, priv->mc_token, &state); + if (err) { -+ netdev_err(net_dev, "ERROR %d getting link state", err); ++ netdev_err(net_dev, "ERROR %d getting link state\n", err); + goto out; + } + @@ -5342,39 +7146,52 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * beyond the DPNI attributes. + */ + if (state.options & DPNI_LINK_OPT_AUTONEG) -+ cmd->autoneg = AUTONEG_ENABLE; ++ link_settings->base.autoneg = AUTONEG_ENABLE; + if (!(state.options & DPNI_LINK_OPT_HALF_DUPLEX)) -+ cmd->duplex = DUPLEX_FULL; -+ ethtool_cmd_speed_set(cmd, state.rate); ++ link_settings->base.duplex = DUPLEX_FULL; ++ link_settings->base.speed = state.rate; + +out: + return err; +} + -+static int dpaa2_eth_set_settings(struct net_device *net_dev, -+ struct ethtool_cmd *cmd) ++#define DPNI_DYNAMIC_LINK_SET_VER_MAJOR 7 ++#define DPNI_DYNAMIC_LINK_SET_VER_MINOR 1 ++static int ++dpaa2_eth_set_link_ksettings(struct net_device *net_dev, ++ const struct ethtool_link_ksettings *link_settings) +{ + struct dpaa2_eth_priv *priv = netdev_priv(net_dev); + struct dpni_link_state state = {0}; + struct dpni_link_cfg cfg = {0}; + int err = 0; + -+ netdev_dbg(net_dev, "Setting link parameters..."); ++ /* If using an older MC version, the DPNI must be down ++ * in order to be able to change link settings. Taking steps to let ++ * the user know that. ++ */ ++ if (dpaa2_eth_cmp_dpni_ver(priv, DPNI_DYNAMIC_LINK_SET_VER_MAJOR, ++ DPNI_DYNAMIC_LINK_SET_VER_MINOR) < 0) { ++ if (netif_running(net_dev)) { ++ netdev_info(net_dev, "Interface must be brought down first.\n"); ++ return -EACCES; ++ } ++ } + -+ /* Need to interrogate on link state to get flow control params */ ++ /* Need to interrogate link state to get flow control params */ + err = dpni_get_link_state(priv->mc_io, 0, priv->mc_token, &state); + if (err) { -+ netdev_err(net_dev, "ERROR %d getting link state", err); ++ netdev_err(net_dev, "Error getting link state\n"); + goto out; + } + + cfg.options = state.options; -+ cfg.rate = ethtool_cmd_speed(cmd); -+ if (cmd->autoneg == AUTONEG_ENABLE) ++ cfg.rate = link_settings->base.speed; ++ if (link_settings->base.autoneg == AUTONEG_ENABLE) + cfg.options |= DPNI_LINK_OPT_AUTONEG; + else + cfg.options &= ~DPNI_LINK_OPT_AUTONEG; -+ if (cmd->duplex == DUPLEX_HALF) ++ if (link_settings->base.duplex == DUPLEX_HALF) + cfg.options |= DPNI_LINK_OPT_HALF_DUPLEX; + else + cfg.options &= ~DPNI_LINK_OPT_HALF_DUPLEX; @@ -5384,7 +7201,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + /* ethtool will be loud enough if we return an error; no point + * in putting our own error message on the console by default + */ -+ netdev_dbg(net_dev, "ERROR %d setting link cfg", err); ++ netdev_dbg(net_dev, "ERROR %d setting link cfg\n", err); + +out: + return err; @@ -5399,13 +7216,13 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + err = dpni_get_link_state(priv->mc_io, 0, priv->mc_token, &state); + if (err) -+ netdev_dbg(net_dev, "ERROR %d getting link state", err); ++ netdev_dbg(net_dev, "Error getting link state\n"); + -+ /* for now, pause frames autonegotiation is not separate */ ++ /* Report general port autonegotiation status */ + pause->autoneg = !!(state.options & DPNI_LINK_OPT_AUTONEG); + pause->rx_pause = !!(state.options & DPNI_LINK_OPT_PAUSE); + pause->tx_pause = pause->rx_pause ^ -+ !!(state.options & DPNI_LINK_OPT_ASYM_PAUSE); ++ !!(state.options & DPNI_LINK_OPT_ASYM_PAUSE); +} + +static int dpaa2_eth_set_pauseparam(struct net_device *net_dev, @@ -5419,7 +7236,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + err = dpni_get_link_state(priv->mc_io, 0, priv->mc_token, &state); + if (err) { -+ netdev_dbg(net_dev, "ERROR %d getting link state", err); ++ netdev_dbg(net_dev, "Error getting link state\n"); + goto out; + } + @@ -5428,9 +7245,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + current_tx_pause = !!(cfg.options & DPNI_LINK_OPT_PAUSE) ^ + !!(cfg.options & DPNI_LINK_OPT_ASYM_PAUSE); + ++ /* We don't support changing pause frame autonegotiation separately ++ * from general port autoneg ++ */ + if (pause->autoneg != !!(state.options & DPNI_LINK_OPT_AUTONEG)) + netdev_warn(net_dev, -+ "WARN: Can't change pause frames autoneg separately\n"); ++ "Cannot change pause frame autoneg separately\n"); + + if (pause->rx_pause) + cfg.options |= DPNI_LINK_OPT_PAUSE; @@ -5444,23 +7264,19 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + err = dpni_set_link_cfg(priv->mc_io, 0, priv->mc_token, &cfg); + if (err) { -+ /* ethtool will be loud enough if we return an error; no point -+ * in putting our own error message on the console by default -+ */ -+ netdev_dbg(net_dev, "ERROR %d setting link cfg", err); ++ netdev_dbg(net_dev, "Error setting link\n"); + goto out; + } + -+ /* Enable / disable taildrops if Tx pause frames have changed */ ++ /* Enable/disable Rx FQ taildrop if Tx pause frames have changed */ + if (current_tx_pause == pause->tx_pause) + goto out; + + priv->tx_pause_frames = pause->tx_pause; + err = set_rx_taildrop(priv); + if (err) -+ netdev_dbg(net_dev, "ERROR %d configuring taildrop", err); ++ netdev_dbg(net_dev, "Error configuring taildrop\n"); + -+ priv->tx_pause_frames = pause->tx_pause; +out: + return err; +} @@ -5501,8 +7317,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct ethtool_stats *stats, + u64 *data) +{ -+ int i = 0; /* Current index in the data array */ -+ int j = 0, k, err; ++ int i = 0; ++ int j, k, err; ++ int num_cnt; + union dpni_statistics dpni_stats; + +#ifdef CONFIG_FSL_QBMAN_DEBUG @@ -5523,38 +7340,22 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + /* Print standard counters, from DPNI statistics */ + for (j = 0; j <= 2; j++) { + err = dpni_get_statistics(priv->mc_io, 0, priv->mc_token, -+ j, &dpni_stats); ++ j, 0, &dpni_stats); + if (err != 0) -+ netdev_warn(net_dev, "Err %d getting DPNI stats page %d", -+ err, j); -+ ++ netdev_warn(net_dev, "dpni_get_stats(%d) failed\n", j); + switch (j) { + case 0: -+ *(data + i++) = dpni_stats.page_0.ingress_all_frames; -+ *(data + i++) = dpni_stats.page_0.ingress_all_bytes; -+ *(data + i++) = dpni_stats.page_0.ingress_multicast_frames; -+ *(data + i++) = dpni_stats.page_0.ingress_multicast_bytes; -+ *(data + i++) = dpni_stats.page_0.ingress_broadcast_frames; -+ *(data + i++) = dpni_stats.page_0.ingress_broadcast_bytes; -+ break; ++ num_cnt = sizeof(dpni_stats.page_0) / sizeof(u64); ++ break; + case 1: -+ *(data + i++) = dpni_stats.page_1.egress_all_frames; -+ *(data + i++) = dpni_stats.page_1.egress_all_bytes; -+ *(data + i++) = dpni_stats.page_1.egress_multicast_frames; -+ *(data + i++) = dpni_stats.page_1.egress_multicast_bytes; -+ *(data + i++) = dpni_stats.page_1.egress_broadcast_frames; -+ *(data + i++) = dpni_stats.page_1.egress_broadcast_bytes; -+ break; ++ num_cnt = sizeof(dpni_stats.page_1) / sizeof(u64); ++ break; + case 2: -+ *(data + i++) = dpni_stats.page_2.ingress_filtered_frames; -+ *(data + i++) = dpni_stats.page_2.ingress_discarded_frames; -+ *(data + i++) = dpni_stats.page_2.ingress_nobuffer_discards; -+ *(data + i++) = dpni_stats.page_2.egress_discarded_frames; -+ *(data + i++) = dpni_stats.page_2.egress_confirmed_frames; -+ break; -+ default: -+ break; ++ num_cnt = sizeof(dpni_stats.page_2) / sizeof(u64); ++ break; + } ++ for (k = 0; k < num_cnt; k++) ++ *(data + i++) = dpni_stats.raw.counter[k]; + } + + /* Print per-cpu extra stats */ @@ -5563,10 +7364,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + for (j = 0; j < sizeof(*extras) / sizeof(__u64); j++) + *((__u64 *)data + i + j) += *((__u64 *)extras + j); + } -+ + i += j; + -+ /* We may be using fewer DPIOs than actual CPUs */ + for (j = 0; j < priv->num_channels; j++) { + ch_stats = &priv->channel[j]->stats; + cdan += ch_stats->cdan; @@ -5617,11 +7416,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +{ + int i, off = 0; + -+ for (i = 0; i < priv->num_hash_fields; i++) { -+ if (priv->hash_fields[i].cls_prot == prot && -+ priv->hash_fields[i].cls_field == field) ++ for (i = 0; i < priv->num_dist_fields; i++) { ++ if (priv->dist_fields[i].cls_prot == prot && ++ priv->dist_fields[i].cls_field == field) + return off; -+ off += priv->hash_fields[i].size; ++ off += priv->dist_fields[i].size; + } + + return -1; @@ -5631,8 +7430,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +{ + u8 i, size = 0; + -+ for (i = 0; i < priv->num_hash_fields; i++) -+ size += priv->hash_fields[i].size; ++ for (i = 0; i < priv->num_dist_fields; i++) ++ size += priv->dist_fields[i].size; + + return size; +} @@ -5649,7 +7448,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + key_size); + goto disable_fs; + } -+ if (priv->num_hash_fields > DPKG_MAX_NUM_OF_EXTRACTS) { ++ if (priv->num_dist_fields > DPKG_MAX_NUM_OF_EXTRACTS) { + dev_info(dev, "Too many key fields (max = %d). Hashing and steering are disabled\n", + DPKG_MAX_NUM_OF_EXTRACTS); + goto disable_fs; @@ -5915,8 +7714,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + fs->location >= rule_cnt) + return -EINVAL; + -+ /* When adding a new rule, check if location if available, -+ * and if not free the existing table entry before inserting ++ /* When adding a new rule, check if location if available ++ * and if not, free the existing table entry before inserting + * the new one + */ + if (add && (priv->cls_rule[fs->location].in_use == true)) @@ -6001,6 +7800,22 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return 0; +} + ++static int set_hash(struct net_device *net_dev, u64 data) ++{ ++ struct dpaa2_eth_priv *priv = netdev_priv(net_dev); ++ u32 key = 0; ++ int i; ++ ++ if (data & RXH_DISCARD) ++ return -EOPNOTSUPP; ++ ++ for (i = 0; i < priv->num_dist_fields; i++) ++ if (priv->dist_fields[i].rxnfc_field & data) ++ key |= priv->dist_fields[i].id; ++ ++ return dpaa2_eth_set_dist_key(priv, DPAA2_ETH_RX_DIST_HASH, key); ++} ++ +static int dpaa2_eth_set_rxnfc(struct net_device *net_dev, + struct ethtool_rxnfc *rxnfc) +{ @@ -6010,11 +7825,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + case ETHTOOL_SRXCLSRLINS: + err = add_cls(net_dev, &rxnfc->fs); + break; -+ + case ETHTOOL_SRXCLSRLDEL: + err = del_cls(net_dev, rxnfc->fs.location); + break; -+ ++ case ETHTOOL_SRXFH: ++ err = set_hash(net_dev, rxnfc->data); ++ break; + default: + err = -EOPNOTSUPP; + } @@ -6031,12 +7847,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + switch (rxnfc->cmd) { + case ETHTOOL_GRXFH: -+ /* we purposely ignore cmd->flow_type, because the hashing key -+ * is the same (and fixed) for all protocols ++ /* we purposely ignore cmd->flow_type for now, because the ++ * classifier only supports a single set of fields for all ++ * protocols + */ -+ rxnfc->data = priv->rx_flow_hash; ++ rxnfc->data = priv->rx_hash_fields; + break; -+ + case ETHTOOL_GRXRINGS: + rxnfc->data = dpaa2_eth_queue_count(priv); + break; @@ -6077,8 +7893,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +const struct ethtool_ops dpaa2_ethtool_ops = { + .get_drvinfo = dpaa2_eth_get_drvinfo, + .get_link = ethtool_op_get_link, -+ .get_settings = dpaa2_eth_get_settings, -+ .set_settings = dpaa2_eth_set_settings, ++ .get_link_ksettings = dpaa2_eth_get_link_ksettings, ++ .set_link_ksettings = dpaa2_eth_set_link_ksettings, + .get_pauseparam = dpaa2_eth_get_pauseparam, + .set_pauseparam = dpaa2_eth_set_pauseparam, + .get_sset_count = dpaa2_eth_get_sset_count, @@ -6268,7 +8084,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#endif /* __FSL_DPKG_H_ */ --- /dev/null +++ b/drivers/staging/fsl-dpaa2/ethernet/dpni-cmd.h -@@ -0,0 +1,658 @@ +@@ -0,0 +1,719 @@ +/* Copyright 2013-2016 Freescale Semiconductor Inc. + * Copyright 2016 NXP + * @@ -6304,6 +8120,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#ifndef _FSL_DPNI_CMD_H +#define _FSL_DPNI_CMD_H + ++#include "dpni.h" ++ +/* DPNI Version */ +#define DPNI_VER_MAJOR 7 +#define DPNI_VER_MINOR 0 @@ -6344,7 +8162,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#define DPNI_CMDID_SET_MAX_FRAME_LENGTH DPNI_CMD(0x216) +#define DPNI_CMDID_GET_MAX_FRAME_LENGTH DPNI_CMD(0x217) +#define DPNI_CMDID_SET_LINK_CFG DPNI_CMD(0x21A) -+#define DPNI_CMDID_SET_TX_SHAPING DPNI_CMD(0x21B) ++#define DPNI_CMDID_SET_TX_SHAPING DPNI_CMD_V2(0x21B) + +#define DPNI_CMDID_SET_MCAST_PROMISC DPNI_CMD(0x220) +#define DPNI_CMDID_GET_MCAST_PROMISC DPNI_CMD(0x221) @@ -6360,11 +8178,13 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +#define DPNI_CMDID_SET_QOS_TBL DPNI_CMD(0x240) +#define DPNI_CMDID_ADD_QOS_ENT DPNI_CMD(0x241) ++#define DPNI_CMDID_REMOVE_QOS_ENT DPNI_CMD(0x242) +#define DPNI_CMDID_ADD_FS_ENT DPNI_CMD(0x244) +#define DPNI_CMDID_REMOVE_FS_ENT DPNI_CMD(0x245) +#define DPNI_CMDID_CLR_FS_ENT DPNI_CMD(0x246) + -+#define DPNI_CMDID_GET_STATISTICS DPNI_CMD(0x25D) ++#define DPNI_CMDID_SET_TX_PRIORITIES DPNI_CMD_V2(0x250) ++#define DPNI_CMDID_GET_STATISTICS DPNI_CMD_V2(0x25D) +#define DPNI_CMDID_RESET_STATISTICS DPNI_CMD(0x25E) +#define DPNI_CMDID_GET_QUEUE DPNI_CMD(0x25F) +#define DPNI_CMDID_SET_QUEUE DPNI_CMD(0x260) @@ -6384,6 +8204,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#define DPNI_CMDID_GET_OFFLOAD DPNI_CMD(0x26B) +#define DPNI_CMDID_SET_OFFLOAD DPNI_CMD(0x26C) + ++#define DPNI_CMDID_SET_RX_FS_DIST DPNI_CMD(0x273) ++#define DPNI_CMDID_SET_RX_HASH_DIST DPNI_CMD(0x274) ++ +/* Macros for accessing command fields smaller than 1byte */ +#define DPNI_MASK(field) \ + GENMASK(DPNI_##field##_SHIFT + DPNI_##field##_SIZE - 1, \ @@ -6578,6 +8401,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +struct dpni_cmd_get_statistics { + u8 page_number; ++ u8 param; +}; + +struct dpni_rsp_get_statistics { @@ -6610,12 +8434,20 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + __le64 options; +}; + ++#define DPNI_COUPLED_SHIFT 0 ++#define DPNI_COUPLED_SIZE 1 ++ +struct dpni_cmd_set_tx_shaping { + /* cmd word 0 */ -+ __le16 max_burst_size; -+ __le16 pad0[3]; ++ __le16 tx_cr_max_burst_size; ++ __le16 tx_er_max_burst_size; ++ __le32 pad; + /* cmd word 1 */ -+ __le32 rate_limit; ++ __le32 tx_cr_rate_limit; ++ __le32 tx_er_rate_limit; ++ /* cmd word 2 */ ++ /* from LSB: coupled:1 */ ++ u8 coupled; +}; + +struct dpni_cmd_set_max_frame_length { @@ -6677,6 +8509,24 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 flags; +}; + ++#define DPNI_SEPARATE_GRP_SHIFT 0 ++#define DPNI_SEPARATE_GRP_SIZE 1 ++#define DPNI_MODE_1_SHIFT 0 ++#define DPNI_MODE_1_SIZE 4 ++#define DPNI_MODE_2_SHIFT 4 ++#define DPNI_MODE_2_SIZE 4 ++ ++struct dpni_cmd_set_tx_priorities { ++ __le16 flags; ++ u8 prio_group_A; ++ u8 prio_group_B; ++ __le32 pad0; ++ u8 modes[4]; ++ __le32 pad1; ++ __le64 pad2; ++ __le16 delta_bandwidth[8]; ++}; ++ +#define DPNI_DIST_MODE_SHIFT 0 +#define DPNI_DIST_MODE_SIZE 4 +#define DPNI_MISS_ACTION_SHIFT 4 @@ -6790,45 +8640,45 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#define DPNI_DISCARD_ON_MISS_SIZE 1 + +struct dpni_cmd_set_qos_table { -+ u32 pad; ++ __le32 pad; + u8 default_tc; + /* only the LSB */ + u8 discard_on_miss; -+ u16 pad1[21]; -+ u64 key_cfg_iova; ++ __le16 pad1[21]; ++ __le64 key_cfg_iova; +}; + +struct dpni_cmd_add_qos_entry { -+ u16 pad; ++ __le16 pad; + u8 tc_id; + u8 key_size; -+ u16 index; -+ u16 pad2; -+ u64 key_iova; -+ u64 mask_iova; ++ __le16 index; ++ __le16 pad2; ++ __le64 key_iova; ++ __le64 mask_iova; +}; + +struct dpni_cmd_remove_qos_entry { + u8 pad1[3]; + u8 key_size; -+ u32 pad2; -+ u64 key_iova; -+ u64 mask_iova; ++ __le32 pad2; ++ __le64 key_iova; ++ __le64 mask_iova; +}; + +struct dpni_cmd_add_fs_entry { + /* cmd word 0 */ -+ u16 options; ++ __le16 options; + u8 tc_id; + u8 key_size; -+ u16 index; -+ u16 flow_id; ++ __le16 index; ++ __le16 flow_id; + /* cmd word 1 */ -+ u64 key_iova; ++ __le64 key_iova; + /* cmd word 2 */ -+ u64 mask_iova; ++ __le64 mask_iova; + /* cmd word 3 */ -+ u64 flc; ++ __le64 flc; +}; + +struct dpni_cmd_remove_fs_entry { @@ -6838,9 +8688,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 key_size; + __le32 pad1; + /* cmd word 1 */ -+ u64 key_iova; ++ __le64 key_iova; + /* cmd word 2 */ -+ u64 mask_iova; ++ __le64 mask_iova; +}; + +struct dpni_cmd_set_taildrop { @@ -6878,6 +8728,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + __le32 threshold; +}; + ++struct dpni_rsp_get_api_version { ++ u16 major; ++ u16 minor; ++}; ++ +#define DPNI_DEST_TYPE_SHIFT 0 +#define DPNI_DEST_TYPE_SIZE 4 +#define DPNI_CONG_UNITS_SHIFT 4 @@ -6889,18 +8744,18 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 tc; + u8 pad[6]; + /* cmd word 1 */ -+ u32 dest_id; -+ u16 notification_mode; ++ __le32 dest_id; ++ __le16 notification_mode; + u8 dest_priority; + /* from LSB: dest_type: 4 units:2 */ + u8 type_units; + /* cmd word 2 */ -+ u64 message_iova; ++ __le64 message_iova; + /* cmd word 3 */ -+ u64 message_ctx; ++ __le64 message_ctx; + /* cmd word 4 */ -+ u32 threshold_entry; -+ u32 threshold_exit; ++ __le32 threshold_entry; ++ __le32 threshold_exit; +}; + +struct dpni_cmd_get_congestion_notification { @@ -6911,25 +8766,47 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +struct dpni_rsp_get_congestion_notification { + /* cmd word 0 */ -+ u64 pad; ++ __le64 pad; + /* cmd word 1 */ -+ u32 dest_id; -+ u16 notification_mode; ++ __le32 dest_id; ++ __le16 notification_mode; + u8 dest_priority; + /* from LSB: dest_type: 4 units:2 */ + u8 type_units; + /* cmd word 2 */ -+ u64 message_iova; ++ __le64 message_iova; + /* cmd word 3 */ -+ u64 message_ctx; ++ __le64 message_ctx; + /* cmd word 4 */ -+ u32 threshold_entry; -+ u32 threshold_exit; ++ __le32 threshold_entry; ++ __le32 threshold_exit; ++}; ++ ++#define DPNI_RX_FS_DIST_ENABLE_SHIFT 0 ++#define DPNI_RX_FS_DIST_ENABLE_SIZE 1 ++struct dpni_cmd_set_rx_fs_dist { ++ __le16 dist_size; ++ u8 enable; ++ u8 tc; ++ __le16 miss_flow_id; ++ __le16 pad; ++ __le64 key_cfg_iova; ++}; ++ ++#define DPNI_RX_HASH_DIST_ENABLE_SHIFT 0 ++#define DPNI_RX_HASH_DIST_ENABLE_SIZE 1 ++struct dpni_cmd_set_rx_hash_dist { ++ __le16 dist_size; ++ u8 enable; ++ u8 tc; ++ __le32 pad; ++ __le64 key_cfg_iova; +}; ++ +#endif /* _FSL_DPNI_CMD_H */ --- /dev/null +++ b/drivers/staging/fsl-dpaa2/ethernet/dpni.c -@@ -0,0 +1,1903 @@ +@@ -0,0 +1,2112 @@ +/* Copyright 2013-2016 Freescale Semiconductor Inc. + * Copyright 2016 NXP + * @@ -6962,8 +8839,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ -+#include "../../fsl-mc/include/mc-sys.h" -+#include "../../fsl-mc/include/mc-cmd.h" ++#include <linux/kernel.h> ++#include <linux/errno.h> ++#include <linux/fsl/mc.h> +#include "dpni.h" +#include "dpni-cmd.h" + @@ -7053,7 +8931,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + int dpni_id, + u16 *token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_open *cmd_params; + + int err; @@ -7091,7 +8969,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u16 token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLOSE, @@ -7119,7 +8997,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + const struct dpni_pools_cfg *cfg) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_set_pools *cmd_params; + int i; + @@ -7156,7 +9034,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u16 token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_ENABLE, @@ -7179,7 +9057,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u16 token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_DISABLE, @@ -7204,7 +9082,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + int *en) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_rsp_is_enabled *rsp_params; + int err; + @@ -7237,7 +9115,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u16 token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_RESET, @@ -7269,7 +9147,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 irq_index, + u8 en) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_set_irq_enable *cmd_params; + + /* prepare command */ @@ -7300,7 +9178,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 irq_index, + u8 *en) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_get_irq_enable *cmd_params; + struct dpni_rsp_get_irq_enable *rsp_params; + @@ -7347,7 +9225,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 irq_index, + u32 mask) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_set_irq_mask *cmd_params; + + /* prepare command */ @@ -7381,7 +9259,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 irq_index, + u32 *mask) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_get_irq_mask *cmd_params; + struct dpni_rsp_get_irq_mask *rsp_params; + int err; @@ -7423,7 +9301,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 irq_index, + u32 *status) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_get_irq_status *cmd_params; + struct dpni_rsp_get_irq_status *rsp_params; + int err; @@ -7466,7 +9344,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 irq_index, + u32 status) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_clear_irq_status *cmd_params; + + /* prepare command */ @@ -7495,7 +9373,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + struct dpni_attr *attr) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_rsp_get_attr *rsp_params; + + int err; @@ -7543,7 +9421,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + struct dpni_error_cfg *cfg) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_set_errors_behavior *cmd_params; + + /* prepare command */ @@ -7575,7 +9453,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + enum dpni_queue_type qtype, + struct dpni_buffer_layout *layout) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_get_buffer_layout *cmd_params; + struct dpni_rsp_get_buffer_layout *rsp_params; + int err; @@ -7623,7 +9501,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + enum dpni_queue_type qtype, + const struct dpni_buffer_layout *layout) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_set_buffer_layout *cmd_params; + + /* prepare command */ @@ -7665,7 +9543,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + enum dpni_offload type, + u32 config) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_set_offload *cmd_params; + + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_OFFLOAD, @@ -7684,7 +9562,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + enum dpni_offload type, + u32 *config) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_get_offload *cmd_params; + struct dpni_rsp_get_offload *rsp_params; + int err; @@ -7726,7 +9604,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + enum dpni_queue_type qtype, + u16 *qdid) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_get_qdid *cmd_params; + struct dpni_rsp_get_qdid *rsp_params; + int err; @@ -7764,7 +9642,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + u16 *data_offset) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_rsp_get_tx_data_offset *rsp_params; + int err; + @@ -7799,7 +9677,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + const struct dpni_link_cfg *cfg) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_set_link_cfg *cmd_params; + + /* prepare command */ @@ -7828,7 +9706,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + struct dpni_link_state *state) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_rsp_get_link_state *rsp_params; + int err; + @@ -7853,19 +9731,23 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +/** + * dpni_set_tx_shaping() - Set the transmit shaping -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPNI object -+ * @tx_shaper: tx shaping configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tx_cr_shaper: TX committed rate shaping configuration ++ * @tx_er_shaper: TX excess rate shaping configuration ++ * @coupled: Committed and excess rate shapers are coupled + * -+ * Return: '0' on Success; Error code otherwise. ++ * Return: '0' on Success; Error code otherwise. + */ +int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, -+ const struct dpni_tx_shaping_cfg *tx_shaper) ++ const struct dpni_tx_shaping_cfg *tx_cr_shaper, ++ const struct dpni_tx_shaping_cfg *tx_er_shaper, ++ int coupled) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_set_tx_shaping *cmd_params; + + /* prepare command */ @@ -7873,8 +9755,13 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + cmd_flags, + token); + cmd_params = (struct dpni_cmd_set_tx_shaping *)cmd.params; -+ cmd_params->max_burst_size = cpu_to_le16(tx_shaper->max_burst_size); -+ cmd_params->rate_limit = cpu_to_le32(tx_shaper->rate_limit); ++ cmd_params->tx_cr_max_burst_size = ++ cpu_to_le16(tx_cr_shaper->max_burst_size); ++ cmd_params->tx_er_max_burst_size = ++ cpu_to_le16(tx_er_shaper->max_burst_size); ++ cmd_params->tx_cr_rate_limit = cpu_to_le32(tx_cr_shaper->rate_limit); ++ cmd_params->tx_er_rate_limit = cpu_to_le32(tx_er_shaper->rate_limit); ++ dpni_set_field(cmd_params->coupled, COUPLED, coupled); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); @@ -7896,7 +9783,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + u16 max_frame_length) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_set_max_frame_length *cmd_params; + + /* prepare command */ @@ -7926,7 +9813,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + u16 *max_frame_length) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_rsp_get_max_frame_length *rsp_params; + int err; + @@ -7961,7 +9848,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + int en) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_set_multicast_promisc *cmd_params; + + /* prepare command */ @@ -7989,7 +9876,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + int *en) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_rsp_get_multicast_promisc *rsp_params; + int err; + @@ -8024,7 +9911,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + int en) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_set_unicast_promisc *cmd_params; + + /* prepare command */ @@ -8052,7 +9939,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + int *en) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_rsp_get_unicast_promisc *rsp_params; + int err; + @@ -8087,7 +9974,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + const u8 mac_addr[6]) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_set_primary_mac_addr *cmd_params; + int i; + @@ -8117,7 +10004,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + u8 mac_addr[6]) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_rsp_get_primary_mac_addr *rsp_params; + int i, err; + @@ -8156,7 +10043,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + u8 mac_addr[6]) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_rsp_get_port_mac_addr *rsp_params; + int i, err; + @@ -8192,7 +10079,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + const u8 mac_addr[6]) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_add_mac_addr *cmd_params; + int i; + @@ -8222,7 +10109,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + const u8 mac_addr[6]) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_remove_mac_addr *cmd_params; + int i; + @@ -8256,7 +10143,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + int unicast, + int multicast) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_clear_mac_filters *cmd_params; + + /* prepare command */ @@ -8272,6 +10159,55 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +} + +/** ++ * dpni_set_tx_priorities() - Set transmission TC priority configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @cfg: Transmission selection configuration ++ * ++ * warning: Allowed only when DPNI is disabled ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_tx_priorities(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ const struct dpni_tx_priorities_cfg *cfg) ++{ ++ struct dpni_cmd_set_tx_priorities *cmd_params; ++ struct fsl_mc_command cmd = { 0 }; ++ int i; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_PRIORITIES, ++ cmd_flags, ++ token); ++ cmd_params = (struct dpni_cmd_set_tx_priorities *)cmd.params; ++ dpni_set_field(cmd_params->flags, ++ SEPARATE_GRP, ++ cfg->separate_groups); ++ cmd_params->prio_group_A = cfg->prio_group_A; ++ cmd_params->prio_group_B = cfg->prio_group_B; ++ ++ for (i = 0; i + 1 < DPNI_MAX_TC; i += 2) { ++ dpni_set_field(cmd_params->modes[i / 2], ++ MODE_1, ++ cfg->tc_sched[i].mode); ++ dpni_set_field(cmd_params->modes[i / 2], ++ MODE_2, ++ cfg->tc_sched[i + 1].mode); ++ } ++ ++ for (i = 0; i < DPNI_MAX_TC; i++) { ++ cmd_params->delta_bandwidth[i] = ++ cpu_to_le16(cfg->tc_sched[i].delta_bandwidth); ++ } ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++/** + * dpni_set_rx_tc_dist() - Set Rx traffic class distribution configuration + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' @@ -8290,7 +10226,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 tc_id, + const struct dpni_rx_tc_dist_cfg *cfg) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_set_rx_tc_dist *cmd_params; + + /* prepare command */ @@ -8330,7 +10266,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + const struct dpni_qos_tbl_cfg *cfg) +{ + struct dpni_cmd_set_qos_table *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_QOS_TBL, @@ -8368,7 +10304,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 index) +{ + struct dpni_cmd_add_qos_entry *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_QOS_ENT, @@ -8386,6 +10322,36 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +} + +/** ++ * dpni_remove_qos_entry() - Remove QoS mapping entry ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @cfg: QoS rule to remove ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_remove_qos_entry(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ const struct dpni_rule_cfg *cfg) ++{ ++ struct dpni_cmd_remove_qos_entry *cmd_params; ++ struct fsl_mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_QOS_ENT, ++ cmd_flags, ++ token); ++ cmd_params = (struct dpni_cmd_remove_qos_entry *)cmd.params; ++ cmd_params->key_size = cfg->key_size; ++ cmd_params->key_iova = cpu_to_le64(cfg->key_iova); ++ cmd_params->mask_iova = cpu_to_le64(cfg->mask_iova); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++/** + * dpni_add_fs_entry() - Add Flow Steering entry for a specific traffic class + * (to select a flow ID) + * @mc_io: Pointer to MC portal's I/O object @@ -8409,7 +10375,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + const struct dpni_fs_action_cfg *action) +{ + struct dpni_cmd_add_fs_entry *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_FS_ENT, @@ -8431,7 +10397,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +/** + * dpni_remove_fs_entry() - Remove Flow Steering entry from a specific -+ * traffic class ++ * traffic class + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPNI object @@ -8447,7 +10413,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + const struct dpni_rule_cfg *cfg) +{ + struct dpni_cmd_remove_fs_entry *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_FS_ENT, @@ -8465,17 +10431,18 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +/** + * dpni_set_congestion_notification() - Set traffic class congestion -+ * notification configuration ++ * notification configuration + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPNI object + * @qtype: Type of queue - Rx, Tx and Tx confirm types are supported + * @tc_id: Traffic class selection (0-7) -+ * @cfg: congestion notification configuration ++ * @cfg: Congestion notification configuration + * + * Return: '0' on Success; error code otherwise. + */ -+int dpni_set_congestion_notification(struct fsl_mc_io *mc_io, ++int dpni_set_congestion_notification( ++ struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + enum dpni_queue_type qtype, @@ -8483,7 +10450,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + const struct dpni_congestion_notification_cfg *cfg) +{ + struct dpni_cmd_set_congestion_notification *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header( @@ -8515,7 +10482,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPNI object + * @qtype: Type of queue - Rx, Tx and Tx confirm types are supported -+ * @tc_id: Traffic class selection (0-7) ++ * @tc_id: bits 7-4 contain ceetm channel index (valid only for TX); ++ * bits 3-0 contain traffic class. ++ * Use macro DPNI_BUILD_CH_TC() to build correct value for ++ * tc_id parameter. + * @cfg: congestion notification configuration + * + * Return: '0' on Success; error code otherwise. @@ -8530,7 +10500,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +{ + struct dpni_rsp_get_congestion_notification *rsp_params; + struct dpni_cmd_get_congestion_notification *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ @@ -8587,7 +10557,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 options, + const struct dpni_queue *queue) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_set_queue *cmd_params; + + /* prepare command */ @@ -8635,7 +10605,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct dpni_queue *queue, + struct dpni_queue_id *qid) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_get_queue *cmd_params; + struct dpni_rsp_get_queue *rsp_params; + int err; @@ -8659,7 +10629,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + queue->destination.id = le32_to_cpu(rsp_params->dest_id); + queue->destination.priority = rsp_params->dest_prio; + queue->destination.type = dpni_get_field(rsp_params->flags, -+ DEST_TYPE); ++ DEST_TYPE); + queue->flc.stash_control = dpni_get_field(rsp_params->flags, + STASH_CTRL); + queue->destination.hold_active = dpni_get_field(rsp_params->flags, @@ -8679,6 +10649,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * @token: Token of DPNI object + * @page: Selects the statistics page to retrieve, see + * DPNI_GET_STATISTICS output. Pages are numbered 0 to 2. ++ * @param: Custom parameter for some pages used to select a certain ++ * statistic source, for example the TC. + * @stat: Structure containing the statistics + * + * Return: '0' on Success; Error code otherwise. @@ -8687,9 +10659,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u16 token, + u8 page, ++ u8 param, + union dpni_statistics *stat) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_get_statistics *cmd_params; + struct dpni_rsp_get_statistics *rsp_params; + int i, err; @@ -8700,6 +10673,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + token); + cmd_params = (struct dpni_cmd_get_statistics *)cmd.params; + cmd_params->page_number = page; ++ cmd_params->param = param; + + /* send command to mc */ + err = mc_send_command(mc_io, &cmd); @@ -8726,7 +10700,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u16 token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_RESET_STATISTICS, @@ -8745,7 +10719,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * @cg_point: Congestion point + * @q_type: Queue type on which the taildrop is configured. + * Only Rx queues are supported for now -+ * @tc: Traffic class to apply this taildrop to ++ * @tc: bits 7-4 contain ceetm channel index (valid only for TX); ++ * bits 3-0 contain traffic class. ++ * Use macro DPNI_BUILD_CH_TC() to build correct value for ++ * tc parameter. + * @q_index: Index of the queue if the DPNI supports multiple queues for + * traffic distribution. Ignored if CONGESTION_POINT is not 0. + * @taildrop: Taildrop structure @@ -8761,7 +10738,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 index, + struct dpni_taildrop *taildrop) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_set_taildrop *cmd_params; + + /* prepare command */ @@ -8789,7 +10766,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * @cg_point: Congestion point + * @q_type: Queue type on which the taildrop is configured. + * Only Rx queues are supported for now -+ * @tc: Traffic class to apply this taildrop to ++ * @tc: bits 7-4 contain ceetm channel index (valid only for TX); ++ * bits 3-0 contain traffic class. ++ * Use macro DPNI_BUILD_CH_TC() to build correct value for ++ * tc parameter. + * @q_index: Index of the queue if the DPNI supports multiple queues for + * traffic distribution. Ignored if CONGESTION_POINT is not 0. + * @taildrop: Taildrop structure @@ -8805,7 +10785,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 index, + struct dpni_taildrop *taildrop) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpni_cmd_get_taildrop *cmd_params; + struct dpni_rsp_get_taildrop *rsp_params; + int err; @@ -8833,9 +10813,115 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + return 0; +} ++ ++/** ++ * dpni_get_api_version() - Get Data Path Network Interface API version ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @major_ver: Major version of data path network interface API ++ * @minor_ver: Minor version of data path network interface API ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_api_version(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 *major_ver, ++ u16 *minor_ver) ++{ ++ struct dpni_rsp_get_api_version *rsp_params; ++ struct fsl_mc_command cmd = { 0 }; ++ int err; ++ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_API_VERSION, ++ cmd_flags, 0); ++ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ rsp_params = (struct dpni_rsp_get_api_version *)cmd.params; ++ *major_ver = le16_to_cpu(rsp_params->major); ++ *minor_ver = le16_to_cpu(rsp_params->minor); ++ ++ return 0; ++} ++ ++/** ++ * dpni_set_rx_fs_dist() - Set Rx traffic class FS distribution ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @cfg: Distribution configuration ++ * If the FS is already enabled with a previous call the classification ++ * key will be changed but all the table rules are kept. If the ++ * existing rules do not match the key the results will not be ++ * predictable. It is the user responsibility to keep key integrity. ++ * If cfg.enable is set to 1 the command will create a flow steering table ++ * and will classify packets according to this table. The packets that ++ * miss all the table rules will be classified according to settings ++ * made in dpni_set_rx_hash_dist() ++ * If cfg.enable is set to 0 the command will clear flow steering table. ++ * The packets will be classified according to settings made in ++ * dpni_set_rx_hash_dist() ++ */ ++int dpni_set_rx_fs_dist(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ const struct dpni_rx_dist_cfg *cfg) ++{ ++ struct dpni_cmd_set_rx_fs_dist *cmd_params; ++ struct fsl_mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_FS_DIST, ++ cmd_flags, ++ token); ++ cmd_params = (struct dpni_cmd_set_rx_fs_dist *)cmd.params; ++ cmd_params->dist_size = le16_to_cpu(cfg->dist_size); ++ dpni_set_field(cmd_params->enable, RX_FS_DIST_ENABLE, cfg->enable); ++ cmd_params->tc = cfg->tc; ++ cmd_params->miss_flow_id = le16_to_cpu(cfg->fs_miss_flow_id); ++ cmd_params->key_cfg_iova = le64_to_cpu(cfg->key_cfg_iova); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++/** ++ * dpni_set_rx_hash_dist() - Set Rx traffic class HASH distribution ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @cfg: Distribution configuration ++ * If cfg.enable is set to 1 the packets will be classified using a hash ++ * function based on the key received in cfg.key_cfg_iova parameter. ++ * If cfg.enable is set to 0 the packets will be sent to the queue configured ++ * in dpni_set_rx_dist_default_queue() call ++ */ ++int dpni_set_rx_hash_dist(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ const struct dpni_rx_dist_cfg *cfg) ++{ ++ struct dpni_cmd_set_rx_hash_dist *cmd_params; ++ struct fsl_mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_HASH_DIST, ++ cmd_flags, ++ token); ++ cmd_params = (struct dpni_cmd_set_rx_hash_dist *)cmd.params; ++ cmd_params->dist_size = le16_to_cpu(cfg->dist_size); ++ dpni_set_field(cmd_params->enable, RX_FS_DIST_ENABLE, cfg->enable); ++ cmd_params->tc = cfg->tc; ++ cmd_params->key_cfg_iova = le64_to_cpu(cfg->key_cfg_iova); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} --- /dev/null +++ b/drivers/staging/fsl-dpaa2/ethernet/dpni.h -@@ -0,0 +1,1053 @@ +@@ -0,0 +1,1172 @@ +/* Copyright 2013-2016 Freescale Semiconductor Inc. + * Copyright 2016 NXP + * @@ -8893,11 +10979,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +/** + * Maximum number of senders + */ -+#define DPNI_MAX_SENDERS 8 ++#define DPNI_MAX_SENDERS 16 +/** + * Maximum distribution size + */ -+#define DPNI_MAX_DIST_SIZE 8 ++#define DPNI_MAX_DIST_SIZE 16 + +/** + * All traffic classes considered; see dpni_set_queue() @@ -9324,6 +11410,24 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u64 egress_confirmed_frames; + } page_2; + /** ++ * struct page_3 - Page_3 statistics structure with values for the ++ * selected TC ++ * @ceetm_dequeue_bytes: Cumulative count of the number of bytes ++ * dequeued ++ * @ceetm_dequeue_frames: Cumulative count of the number of frames ++ * dequeued ++ * @ceetm_reject_bytes: Cumulative count of the number of bytes in all ++ * frames whose enqueue was rejected ++ * @ceetm_reject_frames: Cumulative count of all frame enqueues ++ * rejected ++ */ ++ struct { ++ u64 ceetm_dequeue_bytes; ++ u64 ceetm_dequeue_frames; ++ u64 ceetm_reject_bytes; ++ u64 ceetm_reject_frames; ++ } page_3; ++ /** + * struct raw - raw statistics structure + */ + struct { @@ -9335,6 +11439,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u16 token, + u8 page, ++ u8 param, + union dpni_statistics *stat); + +int dpni_reset_statistics(struct fsl_mc_io *mc_io, @@ -9400,14 +11505,16 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * @max_burst_size: burst size in bytes (up to 64KB) + */ +struct dpni_tx_shaping_cfg { -+ u32 rate_limit; -+ u16 max_burst_size; ++ u32 rate_limit; ++ u16 max_burst_size; +}; + -+int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ const struct dpni_tx_shaping_cfg *tx_shaper); ++int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ const struct dpni_tx_shaping_cfg *tx_cr_shaper, ++ const struct dpni_tx_shaping_cfg *tx_er_shaper, ++ int coupled); + +int dpni_set_max_frame_length(struct fsl_mc_io *mc_io, + u32 cmd_flags, @@ -9530,6 +11637,50 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + const struct dpni_qos_tbl_cfg *cfg); + +/** ++ * enum dpni_tx_schedule_mode - DPNI Tx scheduling mode ++ * @DPNI_TX_SCHED_STRICT_PRIORITY: strict priority ++ * @DPNI_TX_SCHED_WEIGHTED_A: weighted based scheduling in group A ++ * @DPNI_TX_SCHED_WEIGHTED_B: weighted based scheduling in group B ++ */ ++enum dpni_tx_schedule_mode { ++ DPNI_TX_SCHED_STRICT_PRIORITY = 0, ++ DPNI_TX_SCHED_WEIGHTED_A, ++ DPNI_TX_SCHED_WEIGHTED_B, ++}; ++ ++/** ++ * struct dpni_tx_schedule_cfg - Structure representing Tx scheduling conf ++ * @mode: Scheduling mode ++ * @delta_bandwidth: Bandwidth represented in weights from 100 to 10000; ++ * not applicable for 'strict-priority' mode; ++ */ ++struct dpni_tx_schedule_cfg { ++ enum dpni_tx_schedule_mode mode; ++ u16 delta_bandwidth; ++}; ++ ++/** ++ * struct dpni_tx_priorities_cfg - Structure representing transmission ++ * priorities for DPNI TCs ++ * @tc_sched: An array of traffic-classes ++ * @prio_group_A: Priority of group A ++ * @prio_group_B: Priority of group B ++ * @separate_groups: Treat A and B groups as separate ++ * @ceetm_ch_idx: ceetm channel index to apply the changes ++ */ ++struct dpni_tx_priorities_cfg { ++ struct dpni_tx_schedule_cfg tc_sched[DPNI_MAX_TC]; ++ u8 prio_group_A; ++ u8 prio_group_B; ++ u8 separate_groups; ++}; ++ ++int dpni_set_tx_priorities(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ const struct dpni_tx_priorities_cfg *cfg); ++ ++/** + * struct dpni_rx_tc_dist_cfg - Rx traffic class distribution configuration + * @dist_size: Set the distribution size; + * supported values: 1,2,3,4,6,7,8,12,14,16,24,28,32,48,56,64,96, @@ -9676,11 +11827,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +/** + * struct dpni_dest_cfg - Structure representing DPNI destination parameters -+ * @dest_type: Destination type -+ * @dest_id: Either DPIO ID or DPCON ID, depending on the destination type -+ * @priority: Priority selection within the DPIO or DPCON channel; valid values -+ * are 0-1 or 0-7, depending on the number of priorities in that -+ * channel; not relevant for 'DPNI_DEST_NONE' option ++ * @dest_type: Destination type ++ * @dest_id: Either DPIO ID or DPCON ID, depending on the destination type ++ * @priority: Priority selection within the DPIO or DPCON channel; valid ++ * values are 0-1 or 0-7, depending on the number of priorities ++ * in that channel; not relevant for 'DPNI_DEST_NONE' option + */ +struct dpni_dest_cfg { + enum dpni_dest dest_type; @@ -9694,34 +11845,34 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * CSCN message is written to message_iova once entering a + * congestion state (see 'threshold_entry') + */ -+#define DPNI_CONG_OPT_WRITE_MEM_ON_ENTER 0x00000001 ++#define DPNI_CONG_OPT_WRITE_MEM_ON_ENTER 0x00000001 +/** + * CSCN message is written to message_iova once exiting a + * congestion state (see 'threshold_exit') + */ -+#define DPNI_CONG_OPT_WRITE_MEM_ON_EXIT 0x00000002 ++#define DPNI_CONG_OPT_WRITE_MEM_ON_EXIT 0x00000002 +/** + * CSCN write will attempt to allocate into a cache (coherent write); + * valid only if 'DPNI_CONG_OPT_WRITE_MEM_<X>' is selected + */ -+#define DPNI_CONG_OPT_COHERENT_WRITE 0x00000004 ++#define DPNI_CONG_OPT_COHERENT_WRITE 0x00000004 +/** + * if 'dest_cfg.dest_type != DPNI_DEST_NONE' CSCN message is sent to + * DPIO/DPCON's WQ channel once entering a congestion state + * (see 'threshold_entry') + */ -+#define DPNI_CONG_OPT_NOTIFY_DEST_ON_ENTER 0x00000008 ++#define DPNI_CONG_OPT_NOTIFY_DEST_ON_ENTER 0x00000008 +/** + * if 'dest_cfg.dest_type != DPNI_DEST_NONE' CSCN message is sent to + * DPIO/DPCON's WQ channel once exiting a congestion state + * (see 'threshold_exit') + */ -+#define DPNI_CONG_OPT_NOTIFY_DEST_ON_EXIT 0x00000010 ++#define DPNI_CONG_OPT_NOTIFY_DEST_ON_EXIT 0x00000010 +/** + * if 'dest_cfg.dest_type != DPNI_DEST_NONE' when the CSCN is written to the + * sw-portal's DQRR, the DQRI interrupt is asserted immediately (if enabled) + */ -+#define DPNI_CONG_OPT_INTR_COALESCING_DISABLED 0x00000020 ++#define DPNI_CONG_OPT_INTR_COALESCING_DISABLED 0x00000020 +/** + * This congestion will trigger flow control or priority flow control. + * This will have effect only if flow control is enabled with @@ -9731,15 +11882,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +/** + * struct dpni_congestion_notification_cfg - congestion notification -+ * configuration -+ * @units: units type -+ * @threshold_entry: above this threshold we enter a congestion state. -+ * set it to '0' to disable it -+ * @threshold_exit: below this threshold we exit the congestion state. ++ * configuration ++ * @units: Units type ++ * @threshold_entry: Above this threshold we enter a congestion state. ++ * set it to '0' to disable it ++ * @threshold_exit: Below this threshold we exit the congestion state. + * @message_ctx: The context that will be part of the CSCN message + * @message_iova: I/O virtual address (must be in DMA-able memory), -+ * must be 16B aligned; valid only if 'DPNI_CONG_OPT_WRITE_MEM_<X>' is -+ * contained in 'options' ++ * must be 16B aligned; valid only if 'DPNI_CONG_OPT_WRITE_MEM_<X>' ++ * is contained in 'options' + * @dest_cfg: CSCN can be send to either DPIO or DPCON WQ channel + * @notification_mode: Mask of available options; use 'DPNI_CONG_OPT_<X>' values + */ @@ -9754,7 +11905,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 notification_mode; +}; + -+int dpni_set_congestion_notification(struct fsl_mc_io *mc_io, ++/** Compose TC parameter for function dpni_set_congestion_notification() ++ * and dpni_get_congestion_notification(). ++ */ ++#define DPNI_BUILD_CH_TC(ceetm_ch_idx, tc) \ ++ ((((ceetm_ch_idx) & 0x0F) << 4) | ((tc) & 0x0F)) ++ ++int dpni_set_congestion_notification( ++ struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + enum dpni_queue_type qtype, @@ -9815,6 +11973,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 key_size; +}; + ++int dpni_get_api_version(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 *major_ver, ++ u16 *minor_ver); ++ +int dpni_add_qos_entry(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, @@ -9832,13 +11995,13 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token); + +/** -+ * Discard matching traffic. If set, this takes precedence over any other ++ * Discard matching traffic. If set, this takes precedence over any other + * configuration and matching traffic is always discarded. + */ + #define DPNI_FS_OPT_DISCARD 0x1 + +/** -+ * Set FLC value. If set, flc member of truct dpni_fs_action_cfg is used to ++ * Set FLC value. If set, flc member of struct dpni_fs_action_cfg is used to + * override the FLC value set per queue. + * For more details check the Frame Descriptor section in the hardware + * documentation. @@ -9847,26 +12010,27 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +/* + * Indicates whether the 6 lowest significant bits of FLC are used for stash -+ * control. If set, the 6 least significant bits in value are interpreted as ++ * control. If set, the 6 least significant bits in value are interpreted as + * follows: + * - bits 0-1: indicates the number of 64 byte units of context that are -+ * stashed. FLC value is interpreted as a memory address in this case, ++ * stashed. FLC value is interpreted as a memory address in this case, + * excluding the 6 LS bits. + * - bits 2-3: indicates the number of 64 byte units of frame annotation -+ * to be stashed. Annotation is placed at FD[ADDR]. ++ * to be stashed. Annotation is placed at FD[ADDR]. + * - bits 4-5: indicates the number of 64 byte units of frame data to be -+ * stashed. Frame data is placed at FD[ADDR] + FD[OFFSET]. ++ * stashed. Frame data is placed at FD[ADDR] + FD[OFFSET]. + * This flag is ignored if DPNI_FS_OPT_SET_FLC is not specified. + */ +#define DPNI_FS_OPT_SET_STASH_CONTROL 0x4 + +/** + * struct dpni_fs_action_cfg - Action configuration for table look-up -+ * @flc: FLC value for traffic matching this rule. Please check the Frame -+ * Descriptor section in the hardware documentation for more information. -+ * @flow_id: Identifies the Rx queue used for matching traffic. Supported -+ * values are in range 0 to num_queue-1. -+ * @options: Any combination of DPNI_FS_OPT_ values. ++ * @flc: FLC value for traffic matching this rule. Please check the ++ * Frame Descriptor section in the hardware documentation for ++ * more information. ++ * @flow_id: Identifies the Rx queue used for matching traffic. Supported ++ * values are in range 0 to num_queue-1. ++ * @options: Any combination of DPNI_FS_OPT_ values. + */ +struct dpni_fs_action_cfg { + u64 flc; @@ -9888,6 +12052,47 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 tc_id, + const struct dpni_rule_cfg *cfg); + ++/** ++ * When used for queue_idx in function dpni_set_rx_dist_default_queue ++ * will signal to dpni to drop all unclassified frames ++ */ ++#define DPNI_FS_MISS_DROP ((uint16_t)-1) ++ ++/** ++ * struct dpni_rx_dist_cfg - distribution configuration ++ * @dist_size: distribution size; supported values: 1,2,3,4,6,7,8, ++ * 12,14,16,24,28,32,48,56,64,96,112,128,192,224,256,384,448, ++ * 512,768,896,1024 ++ * @key_cfg_iova: I/O virtual address of 256 bytes DMA-able memory filled with ++ * the extractions to be used for the distribution key by calling ++ * dpkg_prepare_key_cfg() relevant only when enable!=0 otherwise ++ * it can be '0' ++ * @enable: enable/disable the distribution. ++ * @tc: TC id for which distribution is set ++ * @fs_miss_flow_id: when packet misses all rules from flow steering table and ++ * hash is disabled it will be put into this queue id; use ++ * DPNI_FS_MISS_DROP to drop frames. The value of this field is ++ * used only when flow steering distribution is enabled and hash ++ * distribution is disabled ++ */ ++struct dpni_rx_dist_cfg { ++ u16 dist_size; ++ u64 key_cfg_iova; ++ u8 enable; ++ u8 tc; ++ u16 fs_miss_flow_id; ++}; ++ ++int dpni_set_rx_fs_dist(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ const struct dpni_rx_dist_cfg *cfg); ++ ++int dpni_set_rx_hash_dist(struct fsl_mc_io *mc_io, ++ u32 cmd_flags, ++ u16 token, ++ const struct dpni_rx_dist_cfg *cfg); ++ +#endif /* __FSL_DPNI_H */ --- /dev/null +++ b/drivers/staging/fsl-dpaa2/ethernet/net.h @@ -10373,61 +12578,154 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +#endif /* __FSL_NET_H */ --- /dev/null -+++ b/drivers/staging/fsl-dpaa2/ethsw/Kconfig -@@ -0,0 +1,6 @@ -+config FSL_DPAA2_ETHSW -+ tristate "DPAA2 Ethernet Switch" -+ depends on FSL_MC_BUS && FSL_DPAA2 -+ default y -+ ---help--- -+ Prototype driver for DPAA2 Ethernet Switch. ---- /dev/null +++ b/drivers/staging/fsl-dpaa2/ethsw/Makefile @@ -0,0 +1,10 @@ ++# SPDX-License-Identifier: GPL-2.0 ++# ++# Makefile for the Freescale DPAA2 Ethernet Switch ++# ++# Copyright 2014-2017 Freescale Semiconductor, Inc. ++# Copyright 2017-2018 NXP + +obj-$(CONFIG_FSL_DPAA2_ETHSW) += dpaa2-ethsw.o + -+dpaa2-ethsw-objs := switch.o dpsw.o ++dpaa2-ethsw-objs := ethsw.o ethsw-ethtool.o dpsw.o +--- /dev/null ++++ b/drivers/staging/fsl-dpaa2/ethsw/README +@@ -0,0 +1,106 @@ ++DPAA2 Ethernet Switch driver ++============================ ++ ++This file provides documentation for the DPAA2 Ethernet Switch driver + -+all: -+ make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules + -+clean: -+ make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean ++Contents ++======== ++ Supported Platforms ++ Architecture Overview ++ Creating an Ethernet Switch ++ Features ++ ++ ++ Supported Platforms ++=================== ++This driver provides networking support for Freescale LS2085A, LS2088A ++DPAA2 SoCs. ++ ++ ++Architecture Overview ++===================== ++The Ethernet Switch in the DPAA2 architecture consists of several hardware ++resources that provide the functionality. These are allocated and ++configured via the Management Complex (MC) portals. MC abstracts most of ++these resources as DPAA2 objects and exposes ABIs through which they can ++be configured and controlled. ++ ++For a more detailed description of the DPAA2 architecture and its object ++abstractions see: ++ drivers/staging/fsl-mc/README.txt ++ ++The Ethernet Switch is built on top of a Datapath Switch (DPSW) object. ++ ++Configuration interface: ++ ++ --------------------- ++ | DPAA2 Switch driver | ++ --------------------- ++ . ++ . ++ ---------- ++ | DPSW API | ++ ---------- ++ . software ++ ================= . ============== ++ . hardware ++ --------------------- ++ | MC hardware portals | ++ --------------------- ++ . ++ . ++ ------ ++ | DPSW | ++ ------ ++ ++Driver uses the switch device driver model and exposes each switch port as ++a network interface, which can be included in a bridge. Traffic switched ++between ports is offloaded into the hardware. Exposed network interfaces ++are not used for I/O, they are used just for configuration. This ++limitation is going to be addressed in the future. ++ ++The DPSW can have ports connected to DPNIs or to PHYs via DPMACs. ++ ++ ++ [ethA] [ethB] [ethC] [ethD] [ethE] [ethF] ++ : : : : : : ++ : : : : : : ++[eth drv] [eth drv] [ ethsw drv ] ++ : : : : : : kernel ++======================================================================== ++ : : : : : : hardware ++ [DPNI] [DPNI] [============= DPSW =================] ++ | | | | | | ++ | ---------- | [DPMAC] [DPMAC] ++ ------------------------------- | | ++ | | ++ [PHY] [PHY] ++ ++For a more detailed description of the Ethernet switch device driver model ++see: ++ Documentation/networking/switchdev.txt ++ ++Creating an Ethernet Switch ++=========================== ++A device is created for the switch objects probed on the MC bus. Each DPSW ++has a number of properties which determine the configuration options and ++associated hardware resources. ++ ++A DPSW object (and the other DPAA2 objects needed for a DPAA2 switch) can ++be added to a container on the MC bus in one of two ways: statically, ++through a Datapath Layout Binary file (DPL) that is parsed by MC at boot ++time; or created dynamically at runtime, via the DPAA2 objects APIs. ++ ++Features ++======== ++Driver configures DPSW to perform hardware switching offload of ++unicast/multicast/broadcast (VLAN tagged or untagged) traffic between its ++ports. ++ ++It allows configuration of hardware learning, flooding, multicast groups, ++port VLAN configuration and STP state. ++ ++Static entries can be added/removed from the FDB. ++ ++Hardware statistics for each port are provided through ethtool -S option. +--- /dev/null ++++ b/drivers/staging/fsl-dpaa2/ethsw/TODO +@@ -0,0 +1,14 @@ ++* Add I/O capabilities on switch port netdevices. This will allow control ++traffic to reach the CPU. ++* Add ACL to redirect control traffic to CPU. ++* Add support for displaying learned FDB entries ++* MC firmware uprev; the DPAA2 objects used by the Ethernet Switch driver ++need to be kept in sync with binary interface changes in MC ++* refine README file ++* cleanup ++ ++NOTE: At least first three of the above are required before getting the ++DPAA2 Ethernet Switch driver out of staging. Another requirement is that ++the fsl-mc bus driver is moved to drivers/bus and dpio driver is moved to ++drivers/soc (this is required for I/O). ++ --- /dev/null +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h -@@ -0,0 +1,851 @@ -+/* Copyright 2013-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 the above-listed copyright holders nor the -+ * names of any contributors may be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") as published by the Free Software -+ * Foundation, either version 2 of that License or (at your option) any -+ * later version. +@@ -0,0 +1,359 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright 2013-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017-2018 NXP + * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. + */ ++ +#ifndef __FSL_DPSW_CMD_H +#define __FSL_DPSW_CMD_H + @@ -10450,47 +12748,28 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#define DPSW_CMDID_DISABLE DPSW_CMD_ID(0x003) +#define DPSW_CMDID_GET_ATTR DPSW_CMD_ID(0x004) +#define DPSW_CMDID_RESET DPSW_CMD_ID(0x005) -+#define DPSW_CMDID_IS_ENABLED DPSW_CMD_ID(0x006) + -+#define DPSW_CMDID_SET_IRQ DPSW_CMD_ID(0x010) -+#define DPSW_CMDID_GET_IRQ DPSW_CMD_ID(0x011) +#define DPSW_CMDID_SET_IRQ_ENABLE DPSW_CMD_ID(0x012) -+#define DPSW_CMDID_GET_IRQ_ENABLE DPSW_CMD_ID(0x013) ++ +#define DPSW_CMDID_SET_IRQ_MASK DPSW_CMD_ID(0x014) -+#define DPSW_CMDID_GET_IRQ_MASK DPSW_CMD_ID(0x015) ++ +#define DPSW_CMDID_GET_IRQ_STATUS DPSW_CMD_ID(0x016) +#define DPSW_CMDID_CLEAR_IRQ_STATUS DPSW_CMD_ID(0x017) + -+#define DPSW_CMDID_SET_REFLECTION_IF DPSW_CMD_ID(0x022) -+ -+#define DPSW_CMDID_ADD_CUSTOM_TPID DPSW_CMD_ID(0x024) -+ -+#define DPSW_CMDID_REMOVE_CUSTOM_TPID DPSW_CMD_ID(0x026) -+ +#define DPSW_CMDID_IF_SET_TCI DPSW_CMD_ID(0x030) +#define DPSW_CMDID_IF_SET_STP DPSW_CMD_ID(0x031) -+#define DPSW_CMDID_IF_SET_ACCEPTED_FRAMES DPSW_CMD_ID(0x032) -+#define DPSW_CMDID_SET_IF_ACCEPT_ALL_VLAN DPSW_CMD_ID(0x033) ++ +#define DPSW_CMDID_IF_GET_COUNTER DPSW_CMD_ID(0x034) -+#define DPSW_CMDID_IF_SET_COUNTER DPSW_CMD_ID(0x035) -+#define DPSW_CMDID_IF_SET_TX_SELECTION DPSW_CMD_ID(0x036) -+#define DPSW_CMDID_IF_ADD_REFLECTION DPSW_CMD_ID(0x037) -+#define DPSW_CMDID_IF_REMOVE_REFLECTION DPSW_CMD_ID(0x038) -+#define DPSW_CMDID_IF_SET_FLOODING_METERING DPSW_CMD_ID(0x039) -+#define DPSW_CMDID_IF_SET_METERING DPSW_CMD_ID(0x03A) -+#define DPSW_CMDID_IF_SET_EARLY_DROP DPSW_CMD_ID(0x03B) + +#define DPSW_CMDID_IF_ENABLE DPSW_CMD_ID(0x03D) +#define DPSW_CMDID_IF_DISABLE DPSW_CMD_ID(0x03E) + -+#define DPSW_CMDID_IF_GET_ATTR DPSW_CMD_ID(0x042) -+ +#define DPSW_CMDID_IF_SET_MAX_FRAME_LENGTH DPSW_CMD_ID(0x044) -+#define DPSW_CMDID_IF_GET_MAX_FRAME_LENGTH DPSW_CMD_ID(0x045) ++ +#define DPSW_CMDID_IF_GET_LINK_STATE DPSW_CMD_ID(0x046) +#define DPSW_CMDID_IF_SET_FLOODING DPSW_CMD_ID(0x047) +#define DPSW_CMDID_IF_SET_BROADCAST DPSW_CMD_ID(0x048) -+#define DPSW_CMDID_IF_SET_MULTICAST DPSW_CMD_ID(0x049) ++ +#define DPSW_CMDID_IF_GET_TCI DPSW_CMD_ID(0x04A) + +#define DPSW_CMDID_IF_SET_LINK_CFG DPSW_CMD_ID(0x04C) @@ -10498,39 +12777,17 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#define DPSW_CMDID_VLAN_ADD DPSW_CMD_ID(0x060) +#define DPSW_CMDID_VLAN_ADD_IF DPSW_CMD_ID(0x061) +#define DPSW_CMDID_VLAN_ADD_IF_UNTAGGED DPSW_CMD_ID(0x062) -+#define DPSW_CMDID_VLAN_ADD_IF_FLOODING DPSW_CMD_ID(0x063) ++ +#define DPSW_CMDID_VLAN_REMOVE_IF DPSW_CMD_ID(0x064) +#define DPSW_CMDID_VLAN_REMOVE_IF_UNTAGGED DPSW_CMD_ID(0x065) +#define DPSW_CMDID_VLAN_REMOVE_IF_FLOODING DPSW_CMD_ID(0x066) +#define DPSW_CMDID_VLAN_REMOVE DPSW_CMD_ID(0x067) -+#define DPSW_CMDID_VLAN_GET_IF DPSW_CMD_ID(0x068) -+#define DPSW_CMDID_VLAN_GET_IF_FLOODING DPSW_CMD_ID(0x069) -+#define DPSW_CMDID_VLAN_GET_IF_UNTAGGED DPSW_CMD_ID(0x06A) -+#define DPSW_CMDID_VLAN_GET_ATTRIBUTES DPSW_CMD_ID(0x06B) -+ -+#define DPSW_CMDID_FDB_GET_MULTICAST DPSW_CMD_ID(0x080) -+#define DPSW_CMDID_FDB_GET_UNICAST DPSW_CMD_ID(0x081) -+#define DPSW_CMDID_FDB_ADD DPSW_CMD_ID(0x082) -+#define DPSW_CMDID_FDB_REMOVE DPSW_CMD_ID(0x083) ++ +#define DPSW_CMDID_FDB_ADD_UNICAST DPSW_CMD_ID(0x084) +#define DPSW_CMDID_FDB_REMOVE_UNICAST DPSW_CMD_ID(0x085) +#define DPSW_CMDID_FDB_ADD_MULTICAST DPSW_CMD_ID(0x086) +#define DPSW_CMDID_FDB_REMOVE_MULTICAST DPSW_CMD_ID(0x087) +#define DPSW_CMDID_FDB_SET_LEARNING_MODE DPSW_CMD_ID(0x088) -+#define DPSW_CMDID_FDB_GET_ATTR DPSW_CMD_ID(0x089) -+ -+#define DPSW_CMDID_ACL_ADD DPSW_CMD_ID(0x090) -+#define DPSW_CMDID_ACL_REMOVE DPSW_CMD_ID(0x091) -+#define DPSW_CMDID_ACL_ADD_ENTRY DPSW_CMD_ID(0x092) -+#define DPSW_CMDID_ACL_REMOVE_ENTRY DPSW_CMD_ID(0x093) -+#define DPSW_CMDID_ACL_ADD_IF DPSW_CMD_ID(0x094) -+#define DPSW_CMDID_ACL_REMOVE_IF DPSW_CMD_ID(0x095) -+#define DPSW_CMDID_ACL_GET_ATTR DPSW_CMD_ID(0x096) -+ -+#define DPSW_CMDID_CTRL_IF_GET_ATTR DPSW_CMD_ID(0x0A0) -+#define DPSW_CMDID_CTRL_IF_SET_POOLS DPSW_CMD_ID(0x0A1) -+#define DPSW_CMDID_CTRL_IF_ENABLE DPSW_CMD_ID(0x0A2) -+#define DPSW_CMDID_CTRL_IF_DISABLE DPSW_CMD_ID(0x0A3) + +/* Macros for accessing command fields smaller than 1byte */ +#define DPSW_MASK(field) \ @@ -10543,12 +12800,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#define dpsw_get_bit(var, bit) \ + (((var) >> (bit)) & GENMASK(0, 0)) + -+static inline u64 dpsw_set_bit(u64 var, unsigned int bit, u8 val) -+{ -+ var |= (u64)val << bit & GENMASK(bit, bit); -+ return var; -+} -+ +struct dpsw_cmd_open { + __le32 dpsw_id; +}; @@ -10585,33 +12836,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 enabled; +}; + -+struct dpsw_cmd_set_irq { -+ /* cmd word 0 */ -+ u8 irq_index; -+ u8 pad[3]; -+ __le32 irq_val; -+ /* cmd word 1 */ -+ __le64 irq_addr; -+ /* cmd word 2 */ -+ __le32 irq_num; -+}; -+ -+struct dpsw_cmd_get_irq { -+ __le32 pad; -+ u8 irq_index; -+}; -+ -+struct dpsw_rsp_get_irq { -+ /* cmd word 0 */ -+ __le32 irq_val; -+ __le32 pad; -+ /* cmd word 1 */ -+ __le64 irq_addr; -+ /* cmd word 2 */ -+ __le32 irq_num; -+ __le32 irq_type; -+}; -+ +struct dpsw_cmd_set_irq_enable { + u8 enable_state; + u8 pad[3]; @@ -10673,17 +12897,13 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + __le16 mem_size; + __le16 max_fdb_mc_groups; + u8 max_meters_per_if; -+ /* from LSB only the ffirst 4 bits */ ++ /* from LSB only the first 4 bits */ + u8 component_type; + __le16 pad; + /* cmd word 3 */ + __le64 options; +}; + -+struct dpsw_cmd_set_reflection_if { -+ __le16 if_id; -+}; -+ +struct dpsw_cmd_if_set_flooding { + __le16 if_id; + /* from LSB: enable:1 */ @@ -10696,12 +12916,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 enable; +}; + -+struct dpsw_cmd_if_set_multicast { -+ __le16 if_id; -+ /* from LSB: enable:1 */ -+ u8 enable; -+}; -+ +#define DPSW_VLAN_ID_SHIFT 0 +#define DPSW_VLAN_ID_SIZE 12 +#define DPSW_DEI_SHIFT 12 @@ -10736,26 +12950,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 state; +}; + -+#define DPSW_FRAME_TYPE_SHIFT 0 -+#define DPSW_FRAME_TYPE_SIZE 4 -+#define DPSW_UNACCEPTED_ACT_SHIFT 4 -+#define DPSW_UNACCEPTED_ACT_SIZE 4 -+ -+struct dpsw_cmd_if_set_accepted_frames { -+ __le16 if_id; -+ /* from LSB: type:4 unaccepted_act:4 */ -+ u8 unaccepted; -+}; -+ -+#define DPSW_ACCEPT_ALL_SHIFT 0 -+#define DPSW_ACCEPT_ALL_SIZE 1 -+ -+struct dpsw_cmd_if_set_accept_all_vlan { -+ __le16 if_id; -+ /* only the least significant bit */ -+ u8 accept_all; -+}; -+ +#define DPSW_COUNTER_TYPE_SHIFT 0 +#define DPSW_COUNTER_TYPE_SIZE 5 + @@ -10770,153 +12964,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + __le64 counter; +}; + -+struct dpsw_cmd_if_set_counter { -+ /* cmd word 0 */ -+ __le16 if_id; -+ /* from LSB: type:5 */ -+ u8 type; -+ /* cmd word 1 */ -+ __le64 counter; -+}; -+ -+#define DPSW_PRIORITY_SELECTOR_SHIFT 0 -+#define DPSW_PRIORITY_SELECTOR_SIZE 3 -+#define DPSW_SCHED_MODE_SHIFT 0 -+#define DPSW_SCHED_MODE_SIZE 4 -+ -+struct dpsw_cmd_if_set_tx_selection { -+ __le16 if_id; -+ /* from LSB: priority_selector:3 */ -+ u8 priority_selector; -+ u8 pad[5]; -+ u8 tc_id[8]; -+ -+ struct dpsw_tc_sched { -+ __le16 delta_bandwidth; -+ u8 mode; -+ u8 pad; -+ } tc_sched[8]; -+}; -+ -+#define DPSW_FILTER_SHIFT 0 -+#define DPSW_FILTER_SIZE 2 -+ -+struct dpsw_cmd_if_reflection { -+ __le16 if_id; -+ __le16 vlan_id; -+ /* only 2 bits from the LSB */ -+ u8 filter; -+}; -+ -+#define DPSW_MODE_SHIFT 0 -+#define DPSW_MODE_SIZE 4 -+#define DPSW_UNITS_SHIFT 4 -+#define DPSW_UNITS_SIZE 4 -+ -+struct dpsw_cmd_if_set_flooding_metering { -+ /* cmd word 0 */ -+ __le16 if_id; -+ u8 pad; -+ /* from LSB: mode:4 units:4 */ -+ u8 mode_units; -+ __le32 cir; -+ /* cmd word 1 */ -+ __le32 eir; -+ __le32 cbs; -+ /* cmd word 2 */ -+ __le32 ebs; -+}; -+ -+struct dpsw_cmd_if_set_metering { -+ /* cmd word 0 */ -+ __le16 if_id; -+ u8 tc_id; -+ /* from LSB: mode:4 units:4 */ -+ u8 mode_units; -+ __le32 cir; -+ /* cmd word 1 */ -+ __le32 eir; -+ __le32 cbs; -+ /* cmd word 2 */ -+ __le32 ebs; -+}; -+ -+#define DPSW_EARLY_DROP_MODE_SHIFT 0 -+#define DPSW_EARLY_DROP_MODE_SIZE 2 -+#define DPSW_EARLY_DROP_UNIT_SHIFT 2 -+#define DPSW_EARLY_DROP_UNIT_SIZE 2 -+ -+struct dpsw_prep_early_drop { -+ /* from LSB: mode:2 units:2 */ -+ u8 conf; -+ u8 pad0[3]; -+ __le32 tail_drop_threshold; -+ u8 green_drop_probability; -+ u8 pad1[7]; -+ __le64 green_max_threshold; -+ __le64 green_min_threshold; -+ __le64 pad2; -+ u8 yellow_drop_probability; -+ u8 pad3[7]; -+ __le64 yellow_max_threshold; -+ __le64 yellow_min_threshold; -+}; -+ -+struct dpsw_cmd_if_set_early_drop { -+ /* cmd word 0 */ -+ u8 pad0; -+ u8 tc_id; -+ __le16 if_id; -+ __le32 pad1; -+ /* cmd word 1 */ -+ __le64 early_drop_iova; -+}; -+ -+struct dpsw_cmd_custom_tpid { -+ __le16 pad; -+ __le16 tpid; -+}; -+ +struct dpsw_cmd_if { + __le16 if_id; +}; + -+#define DPSW_ADMIT_UNTAGGED_SHIFT 0 -+#define DPSW_ADMIT_UNTAGGED_SIZE 4 -+#define DPSW_ENABLED_SHIFT 5 -+#define DPSW_ENABLED_SIZE 1 -+#define DPSW_ACCEPT_ALL_VLAN_SHIFT 6 -+#define DPSW_ACCEPT_ALL_VLAN_SIZE 1 -+ -+struct dpsw_rsp_if_get_attr { -+ /* cmd word 0 */ -+ /* from LSB: admit_untagged:4 enabled:1 accept_all_vlan:1 */ -+ u8 conf; -+ u8 pad1; -+ u8 num_tcs; -+ u8 pad2; -+ __le16 qdid; -+ /* cmd word 1 */ -+ __le32 options; -+ __le32 pad3; -+ /* cmd word 2 */ -+ __le32 rate; -+}; -+ +struct dpsw_cmd_if_set_max_frame_length { + __le16 if_id; + __le16 frame_length; +}; + -+struct dpsw_cmd_if_get_max_frame_length { -+ __le16 if_id; -+}; -+ -+struct dpsw_rsp_if_get_max_frame_length { -+ __le16 pad; -+ __le16 frame_length; -+}; -+ +struct dpsw_cmd_if_set_link_cfg { + /* cmd word 0 */ + __le16 if_id; @@ -10957,7 +13013,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + __le16 pad0; + __le16 vlan_id; + __le32 pad1; -+ /* cmd word 1 */ ++ /* cmd word 1-4 */ + __le64 if_id[4]; +}; + @@ -10966,59 +13022,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + __le16 vlan_id; +}; + -+struct dpsw_cmd_vlan_get_attr { -+ __le16 vlan_id; -+}; -+ -+struct dpsw_rsp_vlan_get_attr { -+ /* cmd word 0 */ -+ __le64 pad; -+ /* cmd word 1 */ -+ __le16 fdb_id; -+ __le16 num_ifs; -+ __le16 num_untagged_ifs; -+ __le16 num_flooding_ifs; -+}; -+ -+struct dpsw_cmd_vlan_get_if { -+ __le16 vlan_id; -+}; -+ -+struct dpsw_rsp_vlan_get_if { -+ /* cmd word 0 */ -+ __le16 pad0; -+ __le16 num_ifs; -+ u8 pad1[4]; -+ /* cmd word 1 */ -+ __le64 if_id[4]; -+}; -+ -+struct dpsw_cmd_vlan_get_if_untagged { -+ __le16 vlan_id; -+}; -+ -+struct dpsw_rsp_vlan_get_if_untagged { -+ /* cmd word 0 */ -+ __le16 pad0; -+ __le16 num_ifs; -+ u8 pad1[4]; -+ /* cmd word 1 */ -+ __le64 if_id[4]; -+}; -+ -+struct dpsw_cmd_vlan_get_if_flooding { -+ __le16 vlan_id; -+}; -+ -+struct dpsw_rsp_vlan_get_if_flooding { -+ /* cmd word 0 */ -+ __le16 pad0; -+ __le16 num_ifs; -+ u8 pad1[4]; -+ /* cmd word 1 */ -+ __le64 if_id[4]; -+}; -+ +struct dpsw_cmd_fdb_add { + __le32 pad; + __le16 fdb_aging_time; @@ -11036,30 +13039,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#define DPSW_ENTRY_TYPE_SHIFT 0 +#define DPSW_ENTRY_TYPE_SIZE 4 + -+struct dpsw_cmd_fdb_add_unicast { -+ /* cmd word 0 */ -+ __le16 fdb_id; -+ u8 mac_addr[6]; -+ /* cmd word 1 */ -+ u8 if_egress; -+ u8 pad; -+ /* only the first 4 bits from LSB */ -+ u8 type; -+}; -+ -+struct dpsw_cmd_fdb_get_unicast { -+ __le16 fdb_id; -+ u8 mac_addr[6]; -+}; -+ -+struct dpsw_rsp_fdb_get_unicast { -+ __le64 pad; -+ __le16 if_egress; -+ /* only first 4 bits from LSB */ -+ u8 type; -+}; -+ -+struct dpsw_cmd_fdb_remove_unicast { ++struct dpsw_cmd_fdb_unicast_op { + /* cmd word 0 */ + __le16 fdb_id; + u8 mac_addr[6]; @@ -11069,7 +13049,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 type; +}; + -+struct dpsw_cmd_fdb_add_multicast { ++struct dpsw_cmd_fdb_multicast_op { + /* cmd word 0 */ + __le16 fdb_id; + __le16 num_ifs; @@ -11079,38 +13059,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + /* cmd word 1 */ + u8 mac_addr[6]; + __le16 pad2; -+ /* cmd word 2 */ -+ __le64 if_id[4]; -+}; -+ -+struct dpsw_cmd_fdb_get_multicast { -+ __le16 fdb_id; -+ u8 mac_addr[6]; -+}; -+ -+struct dpsw_rsp_fdb_get_multicast { -+ /* cmd word 0 */ -+ __le64 pad0; -+ /* cmd word 1 */ -+ __le16 num_ifs; -+ /* only the first 4 bits from LSB */ -+ u8 type; -+ u8 pad1[5]; -+ /* cmd word 2 */ -+ __le64 if_id[4]; -+}; -+ -+struct dpsw_cmd_fdb_remove_multicast { -+ /* cmd word 0 */ -+ __le16 fdb_id; -+ __le16 num_ifs; -+ /* only the first 4 bits from LSB */ -+ u8 type; -+ u8 pad[3]; -+ /* cmd word 1 */ -+ u8 mac_addr[6]; -+ __le16 pad2; -+ /* cmd word 2 */ ++ /* cmd word 2-5 */ + __le64 if_id[4]; +}; + @@ -11123,125 +13072,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 mode; +}; + -+struct dpsw_cmd_fdb_get_attr { -+ __le16 fdb_id; -+}; -+ -+struct dpsw_rsp_fdb_get_attr { -+ /* cmd word 0 */ -+ __le16 pad; -+ __le16 max_fdb_entries; -+ __le16 fdb_aging_time; -+ __le16 num_fdb_mc_groups; -+ /* cmd word 1 */ -+ __le16 max_fdb_mc_groups; -+ /* only the first 4 bits from LSB */ -+ u8 learning_mode; -+}; -+ -+struct dpsw_cmd_acl_add { -+ __le16 pad; -+ __le16 max_entries; -+}; -+ -+struct dpsw_rsp_acl_add { -+ __le16 acl_id; -+}; -+ -+struct dpsw_cmd_acl_remove { -+ __le16 acl_id; -+}; -+ -+struct dpsw_prep_acl_entry { -+ u8 match_l2_dest_mac[6]; -+ __le16 match_l2_tpid; -+ -+ u8 match_l2_source_mac[6]; -+ __le16 match_l2_vlan_id; -+ -+ __le32 match_l3_dest_ip; -+ __le32 match_l3_source_ip; -+ -+ __le16 match_l4_dest_port; -+ __le16 match_l4_source_port; -+ __le16 match_l2_ether_type; -+ u8 match_l2_pcp_dei; -+ u8 match_l3_dscp; -+ -+ u8 mask_l2_dest_mac[6]; -+ __le16 mask_l2_tpid; -+ -+ u8 mask_l2_source_mac[6]; -+ __le16 mask_l2_vlan_id; -+ -+ __le32 mask_l3_dest_ip; -+ __le32 mask_l3_source_ip; -+ -+ __le16 mask_l4_dest_port; -+ __le16 mask_l4_source_port; -+ __le16 mask_l2_ether_type; -+ u8 mask_l2_pcp_dei; -+ u8 mask_l3_dscp; -+ -+ u8 match_l3_protocol; -+ u8 mask_l3_protocol; -+}; -+ -+#define DPSW_RESULT_ACTION_SHIFT 0 -+#define DPSW_RESULT_ACTION_SIZE 4 -+ -+struct dpsw_cmd_acl_entry { -+ __le16 acl_id; -+ __le16 result_if_id; -+ __le32 precedence; -+ /* from LSB only the first 4 bits */ -+ u8 result_action; -+ u8 pad[7]; -+ __le64 pad2[4]; -+ __le64 key_iova; -+}; -+ -+struct dpsw_cmd_acl_if { -+ /* cmd word 0 */ -+ __le16 acl_id; -+ __le16 num_ifs; -+ __le32 pad; -+ /* cmd word 1 */ -+ __le64 if_id[4]; -+}; -+ -+struct dpsw_cmd_acl_get_attr { -+ __le16 acl_id; -+}; -+ -+struct dpsw_rsp_acl_get_attr { -+ /* cmd word 0 */ -+ __le64 pad; -+ /* cmd word 1 */ -+ __le16 max_entries; -+ __le16 num_entries; -+ __le16 num_ifs; -+}; -+ -+struct dpsw_rsp_ctrl_if_get_attr { -+ /* cmd word 0 */ -+ __le64 pad; -+ /* cmd word 1 */ -+ __le32 rx_fqid; -+ __le32 rx_err_fqid; -+ /* cmd word 2 */ -+ __le32 tx_err_conf_fqid; -+}; -+ -+struct dpsw_cmd_ctrl_if_set_pools { -+ u8 num_dpbp; -+ /* from LSB: POOL0_BACKUP_POOL:1 ... POOL7_BACKUP_POOL */ -+ u8 backup_pool; -+ __le16 pad; -+ __le32 dpbp_id[8]; -+ __le16 buffer_size[8]; -+}; -+ +struct dpsw_rsp_get_api_version { + __le16 version_major; + __le16 version_minor; @@ -11250,74 +13080,27 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#endif /* __FSL_DPSW_CMD_H */ --- /dev/null +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c -@@ -0,0 +1,2762 @@ -+/* Copyright 2013-2015 Freescale Semiconductor Inc. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are met: -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * * Neither the name of the above-listed copyright holders nor the -+ * names of any contributors may be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") as published by the Free Software -+ * Foundation, either version 2 of that License or (at your option) any -+ * later version. +@@ -0,0 +1,1165 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright 2013-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017-2018 NXP + * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. + */ -+#include "../../fsl-mc/include/mc-sys.h" -+#include "../../fsl-mc/include/mc-cmd.h" ++ ++#include <linux/fsl/mc.h> +#include "dpsw.h" +#include "dpsw-cmd.h" + +static void build_if_id_bitmap(__le64 *bmap, + const u16 *id, -+ const u16 num_ifs) { ++ const u16 num_ifs) ++{ + int i; + -+ for (i = 0; (i < num_ifs) && (i < DPSW_MAX_IF); i++) -+ bmap[id[i] / 64] = dpsw_set_bit(bmap[id[i] / 64], -+ (id[i] % 64), -+ 1); -+} -+ -+static void read_if_id_bitmap(u16 *if_id, -+ u16 *num_ifs, -+ __le64 *bmap) { -+ int bitmap[DPSW_MAX_IF] = { 0 }; -+ int i, j = 0; -+ int count = 0; -+ -+ for (i = 0; i < DPSW_MAX_IF; i++) { -+ bitmap[i] = dpsw_get_bit(le64_to_cpu(bmap[i / 64]), -+ i % 64); -+ count += bitmap[i]; -+ } -+ -+ *num_ifs = (u16)count; -+ -+ for (i = 0; (i < DPSW_MAX_IF) && (j < count); i++) { -+ if (bitmap[i]) { -+ if_id[j] = (u16)i; -+ j++; -+ } ++ for (i = 0; (i < num_ifs) && (i < DPSW_MAX_IF); i++) { ++ if (id[i] < DPSW_MAX_IF) ++ bmap[id[i] / 64] |= cpu_to_le64(BIT_MASK(id[i] % 64)); + } +} + @@ -11343,7 +13126,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + int dpsw_id, + u16 *token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_open *cmd_params; + int err; + @@ -11380,7 +13163,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u16 token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPSW_CMDID_CLOSE, @@ -11403,7 +13186,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u16 token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPSW_CMDID_ENABLE, @@ -11426,7 +13209,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u16 token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPSW_CMDID_DISABLE, @@ -11438,41 +13221,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +} + +/** -+ * dpsw_is_enabled() - Check if the DPSW is enabled -+ * -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @en: Returns '1' if object is enabled; '0' otherwise -+ * -+ * Return: '0' on Success; Error code otherwise -+ */ -+int dpsw_is_enabled(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ int *en) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_rsp_is_enabled *cmd_rsp; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IS_ENABLED, cmd_flags, -+ token); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ cmd_rsp = (struct dpsw_rsp_is_enabled *)cmd.params; -+ *en = dpsw_get_field(cmd_rsp->enabled, ENABLE); -+ -+ return 0; -+} -+ -+/** + * dpsw_reset() - Reset the DPSW, returns the object to initial state. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' @@ -11484,7 +13232,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u16 token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPSW_CMDID_RESET, @@ -11496,86 +13244,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +} + +/** -+ * dpsw_set_irq() - Set IRQ information for the DPSW to trigger an interrupt. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @irq_index: Identifies the interrupt index to configure -+ * @irq_cfg: IRQ configuration -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpsw_set_irq(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u8 irq_index, -+ struct dpsw_irq_cfg *irq_cfg) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_set_irq *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_IRQ, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_set_irq *)cmd.params; -+ cmd_params->irq_index = irq_index; -+ cmd_params->irq_val = cpu_to_le32(irq_cfg->val); -+ cmd_params->irq_addr = cpu_to_le64(irq_cfg->addr); -+ cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpsw_get_irq() - Get IRQ information from the DPSW -+ * -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @irq_index: The interrupt index to configure -+ * @type: Interrupt type: 0 represents message interrupt -+ * type (both irq_addr and irq_val are valid) -+ * @irq_cfg: IRQ attributes -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpsw_get_irq(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u8 irq_index, -+ int *type, -+ struct dpsw_irq_cfg *irq_cfg) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_get_irq *cmd_params; -+ struct dpsw_rsp_get_irq *rsp_params; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_IRQ, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_get_irq *)cmd.params; -+ cmd_params->irq_index = irq_index; -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ rsp_params = (struct dpsw_rsp_get_irq *)cmd.params; -+ irq_cfg->addr = le64_to_cpu(rsp_params->irq_addr); -+ irq_cfg->val = le32_to_cpu(rsp_params->irq_val); -+ irq_cfg->irq_num = le32_to_cpu(rsp_params->irq_num); -+ *type = le32_to_cpu(rsp_params->irq_type); -+ -+ return 0; -+} -+ -+/** + * dpsw_set_irq_enable() - Set overall interrupt state. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' @@ -11596,7 +13264,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 irq_index, + u8 en) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_set_irq_enable *cmd_params; + + /* prepare command */ @@ -11633,7 +13301,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 irq_index, + u32 mask) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_set_irq_mask *cmd_params; + + /* prepare command */ @@ -11666,7 +13334,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 irq_index, + u32 *status) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_get_irq_status *cmd_params; + struct dpsw_rsp_get_irq_status *rsp_params; + int err; @@ -11709,7 +13377,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 irq_index, + u32 status) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_clear_irq_status *cmd_params; + + /* prepare command */ @@ -11738,7 +13406,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + struct dpsw_attr *attr) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_rsp_get_attr *rsp_params; + int err; + @@ -11773,36 +13441,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +} + +/** -+ * dpsw_set_reflection_if() - Set target interface for reflected interfaces. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @if_id: Interface Id -+ * -+ * Only one reflection receive interface is allowed per switch -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+int dpsw_set_reflection_if(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_set_reflection_if *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_REFLECTION_IF, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_set_reflection_if *)cmd.params; -+ cmd_params->if_id = cpu_to_le16(if_id); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** + * dpsw_if_set_link_cfg() - Set the link configuration. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' @@ -11818,7 +13456,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 if_id, + struct dpsw_link_cfg *cfg) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_if_set_link_cfg *cmd_params; + + /* prepare command */ @@ -11850,7 +13488,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 if_id, + struct dpsw_link_state *state) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_if_get_link_state *cmd_params; + struct dpsw_rsp_if_get_link_state *rsp_params; + int err; @@ -11890,9 +13528,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u16 token, + u16 if_id, -+ int en) ++ u8 en) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_if_set_flooding *cmd_params; + + /* prepare command */ @@ -11921,9 +13559,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u16 token, + u16 if_id, -+ int en) ++ u8 en) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_if_set_broadcast *cmd_params; + + /* prepare command */ @@ -11939,37 +13577,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +} + +/** -+ * dpsw_if_set_multicast() - Enable/disable multicast for particular interface -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @if_id: Interface Identifier -+ * @en: 1 - enable, 0 - disable -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+int dpsw_if_set_multicast(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id, -+ int en) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_if_set_multicast *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_MULTICAST, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_if_set_multicast *)cmd.params; -+ cmd_params->if_id = cpu_to_le16(if_id); -+ dpsw_set_field(cmd_params->enable, ENABLE, en); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** + * dpsw_if_set_tci() - Set default VLAN Tag Control Information (TCI) + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' @@ -11985,8 +13592,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 if_id, + const struct dpsw_tci_cfg *cfg) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_if_set_tci *cmd_params; ++ u16 tmp_conf = 0; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_TCI, @@ -11994,10 +13602,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + token); + cmd_params = (struct dpsw_cmd_if_set_tci *)cmd.params; + cmd_params->if_id = cpu_to_le16(if_id); -+ dpsw_set_field(cmd_params->conf, VLAN_ID, cfg->vlan_id); -+ dpsw_set_field(cmd_params->conf, DEI, cfg->dei); -+ dpsw_set_field(cmd_params->conf, PCP, cfg->pcp); -+ cmd_params->conf = cpu_to_le16(cmd_params->conf); ++ dpsw_set_field(tmp_conf, VLAN_ID, cfg->vlan_id); ++ dpsw_set_field(tmp_conf, DEI, cfg->dei); ++ dpsw_set_field(tmp_conf, PCP, cfg->pcp); ++ cmd_params->conf = cpu_to_le16(tmp_conf); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); @@ -12019,7 +13627,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 if_id, + struct dpsw_tci_cfg *cfg) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_if_get_tci *cmd_params; + struct dpsw_rsp_if_get_tci *rsp_params; + int err; @@ -12064,7 +13672,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 if_id, + const struct dpsw_stp_cfg *cfg) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_if_set_stp *cmd_params; + + /* prepare command */ @@ -12081,83 +13689,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +} + +/** -+ * dpsw_if_set_accepted_frames() -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @if_id: Interface Identifier -+ * @cfg: Frame types configuration -+ * -+ * When is admit_only_vlan_tagged- the device will discard untagged -+ * frames or Priority-Tagged frames received on this interface. -+ * When admit_only_untagged- untagged frames or Priority-Tagged -+ * frames received on this interface will be accepted and assigned -+ * to a VID based on the PVID and VID Set for this interface. -+ * When admit_all - the device will accept VLAN tagged, untagged -+ * and priority tagged frames. -+ * The default is admit_all -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+int dpsw_if_set_accepted_frames(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id, -+ const struct dpsw_accepted_frames_cfg *cfg) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_if_set_accepted_frames *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_ACCEPTED_FRAMES, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_if_set_accepted_frames *)cmd.params; -+ cmd_params->if_id = cpu_to_le16(if_id); -+ dpsw_set_field(cmd_params->unaccepted, FRAME_TYPE, cfg->type); -+ dpsw_set_field(cmd_params->unaccepted, UNACCEPTED_ACT, -+ cfg->unaccept_act); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpsw_if_set_accept_all_vlan() -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @if_id: Interface Identifier -+ * @accept_all: Accept or drop frames having different VLAN -+ * -+ * When this is accept (FALSE), the device will discard incoming -+ * frames for VLANs that do not include this interface in its -+ * Member set. When accept (TRUE), the interface will accept all incoming frames -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+int dpsw_if_set_accept_all_vlan(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id, -+ int accept_all) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_if_set_accept_all_vlan *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_IF_ACCEPT_ALL_VLAN, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_if_set_accept_all_vlan *)cmd.params; -+ cmd_params->if_id = cpu_to_le16(if_id); -+ dpsw_set_field(cmd_params->accept_all, ACCEPT_ALL, accept_all); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** + * dpsw_if_get_counter() - Get specific counter of particular interface + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' @@ -12175,7 +13706,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + enum dpsw_counter type, + u64 *counter) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_if_get_counter *cmd_params; + struct dpsw_rsp_if_get_counter *rsp_params; + int err; @@ -12201,352 +13732,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +} + +/** -+ * dpsw_if_set_counter() - Set specific counter of particular interface -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @if_id: Interface Identifier -+ * @type: Counter type -+ * @counter: New counter value -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+int dpsw_if_set_counter(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id, -+ enum dpsw_counter type, -+ u64 counter) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_if_set_counter *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_COUNTER, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_if_set_counter *)cmd.params; -+ cmd_params->if_id = cpu_to_le16(if_id); -+ cmd_params->counter = cpu_to_le64(counter); -+ dpsw_set_field(cmd_params->type, COUNTER_TYPE, type); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpsw_if_set_tx_selection() - Function is used for mapping variety -+ * of frame fields -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @if_id: Interface Identifier -+ * @cfg: Traffic class mapping configuration -+ * -+ * Function is used for mapping variety of frame fields (DSCP, PCP) -+ * to Traffic Class. Traffic class is a number -+ * in the range from 0 to 7 -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+int dpsw_if_set_tx_selection(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id, -+ const struct dpsw_tx_selection_cfg *cfg) -+{ -+ struct dpsw_cmd_if_set_tx_selection *cmd_params; -+ struct mc_command cmd = { 0 }; -+ int i; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_TX_SELECTION, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_if_set_tx_selection *)cmd.params; -+ cmd_params->if_id = cpu_to_le16(if_id); -+ dpsw_set_field(cmd_params->priority_selector, PRIORITY_SELECTOR, -+ cfg->priority_selector); -+ -+ for (i = 0; i < 8; i++) { -+ cmd_params->tc_sched[i].delta_bandwidth = -+ cpu_to_le16(cfg->tc_sched[i].delta_bandwidth); -+ dpsw_set_field(cmd_params->tc_sched[i].mode, SCHED_MODE, -+ cfg->tc_sched[i].mode); -+ cmd_params->tc_id[i] = cfg->tc_id[i]; -+ } -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpsw_if_add_reflection() - Identify interface to be reflected or mirrored -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @if_id: Interface Identifier -+ * @cfg: Reflection configuration -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+int dpsw_if_add_reflection(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id, -+ const struct dpsw_reflection_cfg *cfg) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_if_reflection *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_ADD_REFLECTION, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_if_reflection *)cmd.params; -+ cmd_params->if_id = cpu_to_le16(if_id); -+ cmd_params->vlan_id = cpu_to_le16(cfg->vlan_id); -+ dpsw_set_field(cmd_params->filter, FILTER, cfg->filter); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpsw_if_remove_reflection() - Remove interface to be reflected or mirrored -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @if_id: Interface Identifier -+ * @cfg: Reflection configuration -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+int dpsw_if_remove_reflection(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id, -+ const struct dpsw_reflection_cfg *cfg) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_if_reflection *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_REMOVE_REFLECTION, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_if_reflection *)cmd.params; -+ cmd_params->if_id = cpu_to_le16(if_id); -+ cmd_params->vlan_id = cpu_to_le16(cfg->vlan_id); -+ dpsw_set_field(cmd_params->filter, FILTER, cfg->filter); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpsw_if_set_flooding_metering() - Set flooding metering -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @if_id: Interface Identifier -+ * @cfg: Metering parameters -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+int dpsw_if_set_flooding_metering(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id, -+ const struct dpsw_metering_cfg *cfg) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_if_set_flooding_metering *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_FLOODING_METERING, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_if_set_flooding_metering *)cmd.params; -+ cmd_params->if_id = cpu_to_le16(if_id); -+ dpsw_set_field(cmd_params->mode_units, MODE, cfg->mode); -+ dpsw_set_field(cmd_params->mode_units, UNITS, cfg->units); -+ cmd_params->cir = cpu_to_le32(cfg->cir); -+ cmd_params->eir = cpu_to_le32(cfg->eir); -+ cmd_params->cbs = cpu_to_le32(cfg->cbs); -+ cmd_params->ebs = cpu_to_le32(cfg->ebs); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpsw_if_set_metering() - Set interface metering for flooding -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @if_id: Interface Identifier -+ * @tc_id: Traffic class ID -+ * @cfg: Metering parameters -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+int dpsw_if_set_metering(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id, -+ u8 tc_id, -+ const struct dpsw_metering_cfg *cfg) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_if_set_metering *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_METERING, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_if_set_metering *)cmd.params; -+ cmd_params->if_id = cpu_to_le16(if_id); -+ cmd_params->tc_id = tc_id; -+ dpsw_set_field(cmd_params->mode_units, MODE, cfg->mode); -+ dpsw_set_field(cmd_params->mode_units, UNITS, cfg->units); -+ cmd_params->cir = cpu_to_le32(cfg->cir); -+ cmd_params->eir = cpu_to_le32(cfg->eir); -+ cmd_params->cbs = cpu_to_le32(cfg->cbs); -+ cmd_params->ebs = cpu_to_le32(cfg->ebs); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpsw_prepare_early_drop() - Prepare an early drop for setting in to interface -+ * @cfg: Early-drop configuration -+ * @early_drop_buf: Zeroed 256 bytes of memory before mapping it to DMA -+ * -+ * This function has to be called before dpsw_if_tc_set_early_drop -+ * -+ */ -+void dpsw_prepare_early_drop(const struct dpsw_early_drop_cfg *cfg, -+ u8 *early_drop_buf) -+{ -+ struct dpsw_prep_early_drop *ext_params; -+ -+ ext_params = (struct dpsw_prep_early_drop *)early_drop_buf; -+ dpsw_set_field(ext_params->conf, EARLY_DROP_MODE, cfg->drop_mode); -+ dpsw_set_field(ext_params->conf, EARLY_DROP_UNIT, cfg->units); -+ ext_params->tail_drop_threshold = cpu_to_le32(cfg->tail_drop_threshold); -+ ext_params->green_drop_probability = cfg->green.drop_probability; -+ ext_params->green_max_threshold = cpu_to_le64(cfg->green.max_threshold); -+ ext_params->green_min_threshold = cpu_to_le64(cfg->green.min_threshold); -+ ext_params->yellow_drop_probability = cfg->yellow.drop_probability; -+ ext_params->yellow_max_threshold = -+ cpu_to_le64(cfg->yellow.max_threshold); -+ ext_params->yellow_min_threshold = -+ cpu_to_le64(cfg->yellow.min_threshold); -+} -+ -+/** -+ * dpsw_if_set_early_drop() - Set interface traffic class early-drop -+ * configuration -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @if_id: Interface Identifier -+ * @tc_id: Traffic class selection (0-7) -+ * @early_drop_iova: I/O virtual address of 64 bytes; -+ * Must be cacheline-aligned and DMA-able memory -+ * -+ * warning: Before calling this function, call dpsw_prepare_if_tc_early_drop() -+ * to prepare the early_drop_iova parameter -+ * -+ * Return: '0' on Success; error code otherwise. -+ */ -+int dpsw_if_set_early_drop(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id, -+ u8 tc_id, -+ u64 early_drop_iova) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_if_set_early_drop *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_EARLY_DROP, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_if_set_early_drop *)cmd.params; -+ cmd_params->tc_id = tc_id; -+ cmd_params->if_id = cpu_to_le16(if_id); -+ cmd_params->early_drop_iova = cpu_to_le64(early_drop_iova); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpsw_add_custom_tpid() - API Configures a distinct Ethernet type value -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @cfg: Tag Protocol identifier -+ * -+ * API Configures a distinct Ethernet type value (or TPID value) -+ * to indicate a VLAN tag in addition to the common -+ * TPID values 0x8100 and 0x88A8. -+ * Two additional TPID's are supported -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+int dpsw_add_custom_tpid(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ const struct dpsw_custom_tpid_cfg *cfg) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_custom_tpid *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ADD_CUSTOM_TPID, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_custom_tpid *)cmd.params; -+ cmd_params->tpid = cpu_to_le16(cfg->tpid); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpsw_remove_custom_tpid - API removes a distinct Ethernet type value -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @cfg: Tag Protocol identifier -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+int dpsw_remove_custom_tpid(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ const struct dpsw_custom_tpid_cfg *cfg) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_custom_tpid *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_REMOVE_CUSTOM_TPID, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_custom_tpid *)cmd.params; -+ cmd_params->tpid = cpu_to_le16(cfg->tpid); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** + * dpsw_if_enable() - Enable Interface + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' @@ -12560,7 +13745,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + u16 if_id) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_if *cmd_params; + + /* prepare command */ @@ -12588,7 +13773,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + u16 if_id) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_if *cmd_params; + + /* prepare command */ @@ -12603,53 +13788,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +} + +/** -+ * dpsw_if_get_attributes() - Function obtains attributes of interface -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @if_id: Interface Identifier -+ * @attr: Returned interface attributes -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+int dpsw_if_get_attributes(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id, -+ struct dpsw_if_attr *attr) -+{ -+ struct dpsw_rsp_if_get_attr *rsp_params; -+ struct dpsw_cmd_if *cmd_params; -+ struct mc_command cmd = { 0 }; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_ATTR, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_if *)cmd.params; -+ cmd_params->if_id = cpu_to_le16(if_id); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ rsp_params = (struct dpsw_rsp_if_get_attr *)cmd.params; -+ attr->num_tcs = rsp_params->num_tcs; -+ attr->rate = le32_to_cpu(rsp_params->rate); -+ attr->options = le32_to_cpu(rsp_params->options); -+ attr->enabled = dpsw_get_field(rsp_params->conf, ENABLED); -+ attr->accept_all_vlan = dpsw_get_field(rsp_params->conf, -+ ACCEPT_ALL_VLAN); -+ attr->admit_untagged = dpsw_get_field(rsp_params->conf, ADMIT_UNTAGGED); -+ attr->qdid = le16_to_cpu(rsp_params->qdid); -+ -+ return 0; -+} -+ -+/** + * dpsw_if_set_max_frame_length() - Set Maximum Receive frame length. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' @@ -12665,7 +13803,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 if_id, + u16 frame_length) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_if_set_max_frame_length *cmd_params; + + /* prepare command */ @@ -12681,45 +13819,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +} + +/** -+ * dpsw_if_get_max_frame_length() - Get Maximum Receive frame length. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @if_id: Interface Identifier -+ * @frame_length: Returned maximum Frame Length -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+int dpsw_if_get_max_frame_length(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id, -+ u16 *frame_length) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_if_get_max_frame_length *cmd_params; -+ struct dpsw_rsp_if_get_max_frame_length *rsp_params; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_MAX_FRAME_LENGTH, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_if_get_max_frame_length *)cmd.params; -+ cmd_params->if_id = cpu_to_le16(if_id); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ rsp_params = (struct dpsw_rsp_if_get_max_frame_length *)cmd.params; -+ *frame_length = le16_to_cpu(rsp_params->frame_length); -+ -+ return 0; -+} -+ -+/** + * dpsw_vlan_add() - Adding new VLAN to DPSW. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' @@ -12742,7 +13841,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 vlan_id, + const struct dpsw_vlan_cfg *cfg) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_vlan_add *cmd_params; + + /* prepare command */ @@ -12778,7 +13877,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 vlan_id, + const struct dpsw_vlan_if_cfg *cfg) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_vlan_manage_if *cmd_params; + + /* prepare command */ @@ -12816,7 +13915,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 vlan_id, + const struct dpsw_vlan_if_cfg *cfg) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_vlan_manage_if *cmd_params; + + /* prepare command */ @@ -12832,45 +13931,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +} + +/** -+ * dpsw_vlan_add_if_flooding() - Define a set of interfaces that should be -+ * included in flooding when frame with unknown destination -+ * unicast MAC arrived. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @vlan_id: VLAN Identifier -+ * @cfg: Set of interfaces that should be used for flooding -+ * -+ * These interfaces should belong to this VLAN. By default all -+ * interfaces are included into flooding list. Providing -+ * un-existing interface or an interface that already in the -+ * flooding list generates an error and the entire command is -+ * ignored. -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+int dpsw_vlan_add_if_flooding(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 vlan_id, -+ const struct dpsw_vlan_if_cfg *cfg) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_vlan_manage_if *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_ADD_IF_FLOODING, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_vlan_manage_if *)cmd.params; -+ cmd_params->vlan_id = cpu_to_le16(vlan_id); -+ build_if_id_bitmap(cmd_params->if_id, cfg->if_id, cfg->num_ifs); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** + * dpsw_vlan_remove_if() - Remove interfaces from an existing VLAN. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' @@ -12889,7 +13949,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 vlan_id, + const struct dpsw_vlan_if_cfg *cfg) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_vlan_manage_if *cmd_params; + + /* prepare command */ @@ -12925,7 +13985,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 vlan_id, + const struct dpsw_vlan_if_cfg *cfg) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_vlan_manage_if *cmd_params; + + /* prepare command */ @@ -12941,38 +14001,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +} + +/** -+ * dpsw_vlan_remove_if_flooding() - Define a set of interfaces that should be -+ * removed from the flooding list. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @vlan_id: VLAN Identifier -+ * @cfg: Set of interfaces used for flooding -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+int dpsw_vlan_remove_if_flooding(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 vlan_id, -+ const struct dpsw_vlan_if_cfg *cfg) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_vlan_manage_if *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_REMOVE_IF_FLOODING, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_vlan_manage_if *)cmd.params; -+ cmd_params->vlan_id = cpu_to_le16(vlan_id); -+ build_if_id_bitmap(cmd_params->if_id, cfg->if_id, cfg->num_ifs); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** + * dpsw_vlan_remove() - Remove an entire VLAN + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' @@ -12986,7 +14014,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + u16 vlan_id) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_vlan_remove *cmd_params; + + /* prepare command */ @@ -13001,244 +14029,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +} + +/** -+ * dpsw_vlan_get_attributes() - Get VLAN attributes -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @vlan_id: VLAN Identifier -+ * @attr: Returned DPSW attributes -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+int dpsw_vlan_get_attributes(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 vlan_id, -+ struct dpsw_vlan_attr *attr) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_vlan_get_attr *cmd_params; -+ struct dpsw_rsp_vlan_get_attr *rsp_params; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_GET_ATTRIBUTES, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_vlan_get_attr *)cmd.params; -+ cmd_params->vlan_id = cpu_to_le16(vlan_id); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ rsp_params = (struct dpsw_rsp_vlan_get_attr *)cmd.params; -+ attr->fdb_id = le16_to_cpu(rsp_params->fdb_id); -+ attr->num_ifs = le16_to_cpu(rsp_params->num_ifs); -+ attr->num_untagged_ifs = le16_to_cpu(rsp_params->num_untagged_ifs); -+ attr->num_flooding_ifs = le16_to_cpu(rsp_params->num_flooding_ifs); -+ -+ return 0; -+} -+ -+/** -+ * dpsw_vlan_get_if() - Get interfaces belong to this VLAN -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @vlan_id: VLAN Identifier -+ * @cfg: Returned set of interfaces belong to this VLAN -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+int dpsw_vlan_get_if(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 vlan_id, -+ struct dpsw_vlan_if_cfg *cfg) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_vlan_get_if *cmd_params; -+ struct dpsw_rsp_vlan_get_if *rsp_params; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_GET_IF, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_vlan_get_if *)cmd.params; -+ cmd_params->vlan_id = cpu_to_le16(vlan_id); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ rsp_params = (struct dpsw_rsp_vlan_get_if *)cmd.params; -+ cfg->num_ifs = le16_to_cpu(rsp_params->num_ifs); -+ read_if_id_bitmap(cfg->if_id, &cfg->num_ifs, rsp_params->if_id); -+ -+ return 0; -+} -+ -+/** -+ * dpsw_vlan_get_if_flooding() - Get interfaces used in flooding for this VLAN -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @vlan_id: VLAN Identifier -+ * @cfg: Returned set of flooding interfaces -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+ -+int dpsw_vlan_get_if_flooding(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 vlan_id, -+ struct dpsw_vlan_if_cfg *cfg) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_vlan_get_if_flooding *cmd_params; -+ struct dpsw_rsp_vlan_get_if_flooding *rsp_params; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_GET_IF_FLOODING, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_vlan_get_if_flooding *)cmd.params; -+ cmd_params->vlan_id = cpu_to_le16(vlan_id); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ rsp_params = (struct dpsw_rsp_vlan_get_if_flooding *)cmd.params; -+ cfg->num_ifs = le16_to_cpu(rsp_params->num_ifs); -+ read_if_id_bitmap(cfg->if_id, &cfg->num_ifs, rsp_params->if_id); -+ -+ return 0; -+} -+ -+/** -+ * dpsw_vlan_get_if_untagged() - Get interfaces that should be transmitted as -+ * untagged -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @vlan_id: VLAN Identifier -+ * @cfg: Returned set of untagged interfaces -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+int dpsw_vlan_get_if_untagged(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 vlan_id, -+ struct dpsw_vlan_if_cfg *cfg) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_vlan_get_if_untagged *cmd_params; -+ struct dpsw_rsp_vlan_get_if_untagged *rsp_params; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_GET_IF_UNTAGGED, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_vlan_get_if_untagged *)cmd.params; -+ cmd_params->vlan_id = cpu_to_le16(vlan_id); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ rsp_params = (struct dpsw_rsp_vlan_get_if_untagged *)cmd.params; -+ cfg->num_ifs = le16_to_cpu(rsp_params->num_ifs); -+ read_if_id_bitmap(cfg->if_id, &cfg->num_ifs, rsp_params->if_id); -+ -+ return 0; -+} -+ -+/** -+ * dpsw_fdb_add() - Add FDB to switch and Returns handle to FDB table for -+ * the reference -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @fdb_id: Returned Forwarding Database Identifier -+ * @cfg: FDB Configuration -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+int dpsw_fdb_add(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 *fdb_id, -+ const struct dpsw_fdb_cfg *cfg) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_fdb_add *cmd_params; -+ struct dpsw_rsp_fdb_add *rsp_params; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_ADD, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_fdb_add *)cmd.params; -+ cmd_params->fdb_aging_time = cpu_to_le16(cfg->fdb_aging_time); -+ cmd_params->num_fdb_entries = cpu_to_le16(cfg->num_fdb_entries); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ rsp_params = (struct dpsw_rsp_fdb_add *)cmd.params; -+ *fdb_id = le16_to_cpu(rsp_params->fdb_id); -+ -+ return 0; -+} -+ -+/** -+ * dpsw_fdb_remove() - Remove FDB from switch -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @fdb_id: Forwarding Database Identifier -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+int dpsw_fdb_remove(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 fdb_id) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_fdb_remove *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_REMOVE, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_fdb_remove *)cmd.params; -+ cmd_params->fdb_id = cpu_to_le16(fdb_id); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** + * dpsw_fdb_add_unicast() - Function adds an unicast entry into MAC lookup table + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' @@ -13254,15 +14044,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 fdb_id, + const struct dpsw_fdb_unicast_cfg *cfg) +{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_fdb_add_unicast *cmd_params; ++ struct fsl_mc_command cmd = { 0 }; ++ struct dpsw_cmd_fdb_unicast_op *cmd_params; + int i; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_ADD_UNICAST, + cmd_flags, + token); -+ cmd_params = (struct dpsw_cmd_fdb_add_unicast *)cmd.params; ++ cmd_params = (struct dpsw_cmd_fdb_unicast_op *)cmd.params; + cmd_params->fdb_id = cpu_to_le16(fdb_id); + cmd_params->if_egress = cpu_to_le16(cfg->if_egress); + for (i = 0; i < 6; i++) @@ -13274,50 +14064,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +} + +/** -+ * dpsw_fdb_get_unicast() - Get unicast entry from MAC lookup table by -+ * unicast Ethernet address -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @fdb_id: Forwarding Database Identifier -+ * @cfg: Returned unicast entry configuration -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+int dpsw_fdb_get_unicast(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 fdb_id, -+ struct dpsw_fdb_unicast_cfg *cfg) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_fdb_get_unicast *cmd_params; -+ struct dpsw_rsp_fdb_get_unicast *rsp_params; -+ int err, i; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_GET_UNICAST, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_fdb_get_unicast *)cmd.params; -+ cmd_params->fdb_id = cpu_to_le16(fdb_id); -+ for (i = 0; i < 6; i++) -+ cmd_params->mac_addr[i] = cfg->mac_addr[5 - i]; -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ rsp_params = (struct dpsw_rsp_fdb_get_unicast *)cmd.params; -+ cfg->if_egress = le16_to_cpu(rsp_params->if_egress); -+ cfg->type = dpsw_get_field(rsp_params->type, ENTRY_TYPE); -+ -+ return 0; -+} -+ -+/** + * dpsw_fdb_remove_unicast() - removes an entry from MAC lookup table + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' @@ -13333,15 +14079,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 fdb_id, + const struct dpsw_fdb_unicast_cfg *cfg) +{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_fdb_remove_unicast *cmd_params; ++ struct fsl_mc_command cmd = { 0 }; ++ struct dpsw_cmd_fdb_unicast_op *cmd_params; + int i; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_REMOVE_UNICAST, + cmd_flags, + token); -+ cmd_params = (struct dpsw_cmd_fdb_remove_unicast *)cmd.params; ++ cmd_params = (struct dpsw_cmd_fdb_unicast_op *)cmd.params; + cmd_params->fdb_id = cpu_to_le16(fdb_id); + for (i = 0; i < 6; i++) + cmd_params->mac_addr[i] = cfg->mac_addr[5 - i]; @@ -13375,15 +14121,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 fdb_id, + const struct dpsw_fdb_multicast_cfg *cfg) +{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_fdb_add_multicast *cmd_params; ++ struct fsl_mc_command cmd = { 0 }; ++ struct dpsw_cmd_fdb_multicast_op *cmd_params; + int i; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_ADD_MULTICAST, + cmd_flags, + token); -+ cmd_params = (struct dpsw_cmd_fdb_add_multicast *)cmd.params; ++ cmd_params = (struct dpsw_cmd_fdb_multicast_op *)cmd.params; + cmd_params->fdb_id = cpu_to_le16(fdb_id); + cmd_params->num_ifs = cpu_to_le16(cfg->num_ifs); + dpsw_set_field(cmd_params->type, ENTRY_TYPE, cfg->type); @@ -13396,51 +14142,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +} + +/** -+ * dpsw_fdb_get_multicast() - Reading multi-cast group by multi-cast Ethernet -+ * address. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @fdb_id: Forwarding Database Identifier -+ * @cfg: Returned multicast entry configuration -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+int dpsw_fdb_get_multicast(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 fdb_id, -+ struct dpsw_fdb_multicast_cfg *cfg) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_fdb_get_multicast *cmd_params; -+ struct dpsw_rsp_fdb_get_multicast *rsp_params; -+ int err, i; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_GET_MULTICAST, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_fdb_get_multicast *)cmd.params; -+ cmd_params->fdb_id = cpu_to_le16(fdb_id); -+ for (i = 0; i < 6; i++) -+ cmd_params->mac_addr[i] = cfg->mac_addr[5 - i]; -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ rsp_params = (struct dpsw_rsp_fdb_get_multicast *)cmd.params; -+ cfg->num_ifs = le16_to_cpu(rsp_params->num_ifs); -+ cfg->type = dpsw_get_field(rsp_params->type, ENTRY_TYPE); -+ read_if_id_bitmap(cfg->if_id, &cfg->num_ifs, rsp_params->if_id); -+ -+ return 0; -+} -+ -+/** + * dpsw_fdb_remove_multicast() - Removing interfaces from an existing multicast + * group. + * @mc_io: Pointer to MC portal's I/O object @@ -13462,15 +14163,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 fdb_id, + const struct dpsw_fdb_multicast_cfg *cfg) +{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_fdb_remove_multicast *cmd_params; ++ struct fsl_mc_command cmd = { 0 }; ++ struct dpsw_cmd_fdb_multicast_op *cmd_params; + int i; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_REMOVE_MULTICAST, + cmd_flags, + token); -+ cmd_params = (struct dpsw_cmd_fdb_remove_multicast *)cmd.params; ++ cmd_params = (struct dpsw_cmd_fdb_multicast_op *)cmd.params; + cmd_params->fdb_id = cpu_to_le16(fdb_id); + cmd_params->num_ifs = cpu_to_le16(cfg->num_ifs); + dpsw_set_field(cmd_params->type, ENTRY_TYPE, cfg->type); @@ -13498,7 +14199,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 fdb_id, + enum dpsw_fdb_learning_mode mode) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_cmd_fdb_set_learning_mode *cmd_params; + + /* prepare command */ @@ -13514,474 +14215,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +} + +/** -+ * dpsw_fdb_get_attributes() - Get FDB attributes -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @fdb_id: Forwarding Database Identifier -+ * @attr: Returned FDB attributes -+ * -+ * Return: Completion status. '0' on Success; Error code otherwise. -+ */ -+int dpsw_fdb_get_attributes(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 fdb_id, -+ struct dpsw_fdb_attr *attr) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_fdb_get_attr *cmd_params; -+ struct dpsw_rsp_fdb_get_attr *rsp_params; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_GET_ATTR, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_fdb_get_attr *)cmd.params; -+ cmd_params->fdb_id = cpu_to_le16(fdb_id); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ rsp_params = (struct dpsw_rsp_fdb_get_attr *)cmd.params; -+ attr->max_fdb_entries = le16_to_cpu(rsp_params->max_fdb_entries); -+ attr->fdb_aging_time = le16_to_cpu(rsp_params->fdb_aging_time); -+ attr->learning_mode = dpsw_get_field(rsp_params->learning_mode, -+ LEARNING_MODE); -+ attr->num_fdb_mc_groups = le16_to_cpu(rsp_params->num_fdb_mc_groups); -+ attr->max_fdb_mc_groups = le16_to_cpu(rsp_params->max_fdb_mc_groups); -+ -+ return 0; -+} -+ -+/** -+ * dpsw_acl_add() - Adds ACL to L2 switch. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @acl_id: Returned ACL ID, for the future reference -+ * @cfg: ACL configuration -+ * -+ * Create Access Control List. Multiple ACLs can be created and -+ * co-exist in L2 switch -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpsw_acl_add(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 *acl_id, -+ const struct dpsw_acl_cfg *cfg) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_acl_add *cmd_params; -+ struct dpsw_rsp_acl_add *rsp_params; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_ADD, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_acl_add *)cmd.params; -+ cmd_params->max_entries = cpu_to_le16(cfg->max_entries); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ rsp_params = (struct dpsw_rsp_acl_add *)cmd.params; -+ *acl_id = le16_to_cpu(rsp_params->acl_id); -+ -+ return 0; -+} -+ -+/** -+ * dpsw_acl_remove() - Removes ACL from L2 switch. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @acl_id: ACL ID -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpsw_acl_remove(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 acl_id) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_acl_remove *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_REMOVE, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_acl_remove *)cmd.params; -+ cmd_params->acl_id = cpu_to_le16(acl_id); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpsw_acl_prepare_entry_cfg() - Set an entry to ACL. -+ * @key: Key -+ * @entry_cfg_buf: Zeroed 256 bytes of memory before mapping it to DMA -+ * -+ * This function has to be called before adding or removing acl_entry -+ * -+ */ -+void dpsw_acl_prepare_entry_cfg(const struct dpsw_acl_key *key, -+ u8 *entry_cfg_buf) -+{ -+ struct dpsw_prep_acl_entry *ext_params; -+ int i; -+ -+ ext_params = (struct dpsw_prep_acl_entry *)entry_cfg_buf; -+ -+ for (i = 0; i < 6; i++) { -+ ext_params->match_l2_dest_mac[i] = -+ key->match.l2_dest_mac[5 - i]; -+ ext_params->match_l2_source_mac[i] = -+ key->match.l2_source_mac[5 - i]; -+ ext_params->mask_l2_dest_mac[i] = -+ key->mask.l2_dest_mac[5 - i]; -+ ext_params->mask_l2_source_mac[i] = -+ key->mask.l2_source_mac[5 - i]; -+ } -+ -+ ext_params->match_l2_tpid = cpu_to_le16(key->match.l2_tpid); -+ ext_params->match_l2_vlan_id = cpu_to_le16(key->match.l2_vlan_id); -+ ext_params->match_l3_dest_ip = cpu_to_le32(key->match.l3_dest_ip); -+ ext_params->match_l3_source_ip = cpu_to_le32(key->match.l3_source_ip); -+ ext_params->match_l4_dest_port = cpu_to_le16(key->match.l4_dest_port); -+ ext_params->match_l2_ether_type = cpu_to_le16(key->match.l2_ether_type); -+ ext_params->match_l2_pcp_dei = key->match.l2_pcp_dei; -+ ext_params->match_l3_dscp = key->match.l3_dscp; -+ ext_params->match_l4_source_port = -+ cpu_to_le16(key->match.l4_source_port); -+ -+ ext_params->mask_l2_tpid = cpu_to_le16(key->mask.l2_tpid); -+ ext_params->mask_l2_vlan_id = cpu_to_le16(key->mask.l2_vlan_id); -+ ext_params->mask_l3_dest_ip = cpu_to_le32(key->mask.l3_dest_ip); -+ ext_params->mask_l3_source_ip = cpu_to_le32(key->mask.l3_source_ip); -+ ext_params->mask_l4_dest_port = cpu_to_le16(key->mask.l4_dest_port); -+ ext_params->mask_l4_source_port = cpu_to_le16(key->mask.l4_source_port); -+ ext_params->mask_l2_ether_type = cpu_to_le16(key->mask.l2_ether_type); -+ ext_params->mask_l2_pcp_dei = key->mask.l2_pcp_dei; -+ ext_params->mask_l3_dscp = key->mask.l3_dscp; -+ ext_params->match_l3_protocol = key->match.l3_protocol; -+ ext_params->mask_l3_protocol = key->mask.l3_protocol; -+} -+ -+/** -+ * dpsw_acl_add_entry() - Adds an entry to ACL. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @acl_id: ACL ID -+ * @cfg: Entry configuration -+ * -+ * warning: This function has to be called after dpsw_acl_set_entry_cfg() -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpsw_acl_add_entry(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 acl_id, -+ const struct dpsw_acl_entry_cfg *cfg) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_acl_entry *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_ADD_ENTRY, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_acl_entry *)cmd.params; -+ cmd_params->acl_id = cpu_to_le16(acl_id); -+ cmd_params->result_if_id = cpu_to_le16(cfg->result.if_id); -+ cmd_params->precedence = cpu_to_le32(cfg->precedence); -+ dpsw_set_field(cmd_params->result_action, RESULT_ACTION, -+ cfg->result.action); -+ cmd_params->key_iova = cpu_to_le64(cfg->key_iova); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpsw_acl_remove_entry() - Removes an entry from ACL. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @acl_id: ACL ID -+ * @cfg: Entry configuration -+ * -+ * warning: This function has to be called after dpsw_acl_set_entry_cfg() -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpsw_acl_remove_entry(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 acl_id, -+ const struct dpsw_acl_entry_cfg *cfg) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_acl_entry *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_REMOVE_ENTRY, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_acl_entry *)cmd.params; -+ cmd_params->acl_id = cpu_to_le16(acl_id); -+ cmd_params->result_if_id = cpu_to_le16(cfg->result.if_id); -+ cmd_params->precedence = cpu_to_le32(cfg->precedence); -+ dpsw_set_field(cmd_params->result_action, RESULT_ACTION, -+ cfg->result.action); -+ cmd_params->key_iova = cpu_to_le64(cfg->key_iova); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpsw_acl_add_if() - Associate interface/interfaces with ACL. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @acl_id: ACL ID -+ * @cfg: Interfaces list -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpsw_acl_add_if(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 acl_id, -+ const struct dpsw_acl_if_cfg *cfg) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_acl_if *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_ADD_IF, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_acl_if *)cmd.params; -+ cmd_params->acl_id = cpu_to_le16(acl_id); -+ cmd_params->num_ifs = cpu_to_le16(cfg->num_ifs); -+ build_if_id_bitmap(cmd_params->if_id, cfg->if_id, cfg->num_ifs); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpsw_acl_remove_if() - De-associate interface/interfaces from ACL. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @acl_id: ACL ID -+ * @cfg: Interfaces list -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpsw_acl_remove_if(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 acl_id, -+ const struct dpsw_acl_if_cfg *cfg) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_acl_if *cmd_params; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_REMOVE_IF, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_acl_if *)cmd.params; -+ cmd_params->acl_id = cpu_to_le16(acl_id); -+ cmd_params->num_ifs = cpu_to_le16(cfg->num_ifs); -+ build_if_id_bitmap(cmd_params->if_id, cfg->if_id, cfg->num_ifs); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpsw_acl_get_attributes() - Get specific counter of particular interface -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @acl_id: ACL Identifier -+ * @attr: Returned ACL attributes -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpsw_acl_get_attributes(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 acl_id, -+ struct dpsw_acl_attr *attr) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_acl_get_attr *cmd_params; -+ struct dpsw_rsp_acl_get_attr *rsp_params; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_GET_ATTR, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_acl_get_attr *)cmd.params; -+ cmd_params->acl_id = cpu_to_le16(acl_id); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ rsp_params = (struct dpsw_rsp_acl_get_attr *)cmd.params; -+ attr->max_entries = le16_to_cpu(rsp_params->max_entries); -+ attr->num_entries = le16_to_cpu(rsp_params->num_entries); -+ attr->num_ifs = le16_to_cpu(rsp_params->num_ifs); -+ -+ return 0; -+} -+ -+/** -+ * dpsw_ctrl_if_get_attributes() - Obtain control interface attributes -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @attr: Returned control interface attributes -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpsw_ctrl_if_get_attributes(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ struct dpsw_ctrl_if_attr *attr) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_rsp_ctrl_if_get_attr *rsp_params; -+ int err; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_GET_ATTR, -+ cmd_flags, -+ token); -+ -+ /* send command to mc*/ -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ /* retrieve response parameters */ -+ rsp_params = (struct dpsw_rsp_ctrl_if_get_attr *)cmd.params; -+ attr->rx_fqid = le32_to_cpu(rsp_params->rx_fqid); -+ attr->rx_err_fqid = le32_to_cpu(rsp_params->rx_err_fqid); -+ attr->tx_err_conf_fqid = le32_to_cpu(rsp_params->tx_err_conf_fqid); -+ -+ return 0; -+} -+ -+/** -+ * dpsw_ctrl_if_set_pools() - Set control interface buffer pools -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * @cfg: Buffer pools configuration -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpsw_ctrl_if_set_pools(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ const struct dpsw_ctrl_if_pools_cfg *pools) -+{ -+ struct mc_command cmd = { 0 }; -+ struct dpsw_cmd_ctrl_if_set_pools *cmd_params; -+ int i; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_SET_POOLS, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpsw_cmd_ctrl_if_set_pools *)cmd.params; -+ cmd_params->num_dpbp = pools->num_dpbp; -+ for (i = 0; i < 8; i++) { -+ cmd_params->backup_pool = dpsw_set_bit(cmd_params->backup_pool, -+ i, -+ pools->pools[i].backup_pool); -+ cmd_params->buffer_size[i] = -+ cpu_to_le16(pools->pools[i].buffer_size); -+ cmd_params->dpbp_id[i] = -+ cpu_to_le32(pools->pools[i].dpbp_id); -+ } -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpsw_ctrl_if_enable() - Enable control interface -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpsw_ctrl_if_enable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token) -+{ -+ struct mc_command cmd = { 0 }; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_ENABLE, -+ cmd_flags, -+ token); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpsw_ctrl_if_disable() - Function disables control interface -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSW object -+ * -+ * Return: '0' on Success; Error code otherwise. -+ */ -+int dpsw_ctrl_if_disable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token) -+{ -+ struct mc_command cmd = { 0 }; -+ -+ /* prepare command */ -+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_DISABLE, -+ cmd_flags, -+ token); -+ -+ /* send command to mc*/ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** + * dpsw_get_api_version() - Get Data Path Switch API version + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' @@ -13995,13 +14228,13 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 *major_ver, + u16 *minor_ver) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpsw_rsp_get_api_version *rsp_params; + int err; + + cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_API_VERSION, -+ cmd_flags, -+ 0); ++ cmd_flags, ++ 0); + + err = mc_send_command(mc_io, &cmd); + if (err) @@ -14015,38 +14248,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +} --- /dev/null +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h -@@ -0,0 +1,1269 @@ -+/* Copyright 2013-2015 Freescale Semiconductor Inc. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are met: -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * * Neither the name of the above-listed copyright holders nor the -+ * names of any contributors may be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") as published by the Free Software -+ * Foundation, either version 2 of that License or (at your option) any -+ * later version. +@@ -0,0 +1,592 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright 2013-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017-2018 NXP + * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. + */ ++ +#ifndef __FSL_DPSW_H +#define __FSL_DPSW_H + @@ -14151,17 +14360,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + } adv; +}; + -+int dpsw_create(struct fsl_mc_io *mc_io, -+ u16 dprc_token, -+ u32 cmd_flags, -+ const struct dpsw_cfg *cfg, -+ u32 *obj_id); -+ -+int dpsw_destroy(struct fsl_mc_io *mc_io, -+ u16 dprc_token, -+ u32 cmd_flags, -+ u32 object_id); -+ +int dpsw_enable(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token); @@ -14170,11 +14368,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u16 token); + -+int dpsw_is_enabled(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ int *en); -+ +int dpsw_reset(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token); @@ -14203,43 +14396,18 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + int irq_num; +}; + -+int dpsw_set_irq(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u8 irq_index, -+ struct dpsw_irq_cfg *irq_cfg); -+ -+int dpsw_get_irq(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u8 irq_index, -+ int *type, -+ struct dpsw_irq_cfg *irq_cfg); -+ +int dpsw_set_irq_enable(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 irq_index, + u8 en); + -+int dpsw_get_irq_enable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u8 irq_index, -+ u8 *en); -+ +int dpsw_set_irq_mask(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 irq_index, + u32 mask); + -+int dpsw_get_irq_mask(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u8 irq_index, -+ u32 *mask); -+ +int dpsw_get_irq_status(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, @@ -14292,11 +14460,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + struct dpsw_attr *attr); + -+int dpsw_set_reflection_if(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id); -+ +/** + * enum dpsw_action - Action selection for special/control frames + * @DPSW_ACTION_DROP: Drop frame @@ -14348,7 +14511,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +struct dpsw_link_state { + u32 rate; + u64 options; -+ int up; ++ u8 up; +}; + +int dpsw_if_get_link_state(struct fsl_mc_io *mc_io, @@ -14361,22 +14524,16 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u16 token, + u16 if_id, -+ int en); ++ u8 en); + +int dpsw_if_set_broadcast(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u16 if_id, -+ int en); -+ -+int dpsw_if_set_multicast(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id, -+ int en); ++ u8 en); + +/** -+ * struct dpsw_tci_cfg - Tag Contorl Information (TCI) configuration ++ * struct dpsw_tci_cfg - Tag Control Information (TCI) configuration + * @pcp: Priority Code Point (PCP): a 3-bit field which refers + * to the IEEE 802.1p priority + * @dei: Drop Eligible Indicator (DEI): a 1-bit field. May be used @@ -14415,10 +14572,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * + */ +enum dpsw_stp_state { -+ DPSW_STP_STATE_BLOCKING = 0, ++ DPSW_STP_STATE_DISABLED = 0, + DPSW_STP_STATE_LISTENING = 1, + DPSW_STP_STATE_LEARNING = 2, -+ DPSW_STP_STATE_FORWARDING = 3 ++ DPSW_STP_STATE_FORWARDING = 3, ++ DPSW_STP_STATE_BLOCKING = 0 +}; + +/** @@ -14451,29 +14609,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; + +/** -+ * struct dpsw_accepted_frames_cfg - Types of frames to accept configuration -+ * @type: Defines ingress accepted frames -+ * @unaccept_act: When a frame is not accepted, it may be discarded or -+ * redirected to control interface depending on this mode -+ */ -+struct dpsw_accepted_frames_cfg { -+ enum dpsw_accepted_frames type; -+ enum dpsw_action unaccept_act; -+}; -+ -+int dpsw_if_set_accepted_frames(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id, -+ const struct dpsw_accepted_frames_cfg *cfg); -+ -+int dpsw_if_set_accept_all_vlan(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id, -+ int accept_all); -+ -+/** + * enum dpsw_counter - Counters types + * @DPSW_CNT_ING_FRAME: Counts ingress frames + * @DPSW_CNT_ING_BYTE: Counts ingress bytes @@ -14510,244 +14645,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + enum dpsw_counter type, + u64 *counter); + -+int dpsw_if_set_counter(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id, -+ enum dpsw_counter type, -+ u64 counter); -+ -+/** -+ * Maximum number of TC -+ */ -+#define DPSW_MAX_TC 8 -+ -+/** -+ * enum dpsw_priority_selector - User priority -+ * @DPSW_UP_PCP: Priority Code Point (PCP): a 3-bit field which -+ * refers to the IEEE 802.1p priority. -+ * @DPSW_UP_DSCP: Differentiated services Code Point (DSCP): 6 bit -+ * field from IP header -+ * -+ */ -+enum dpsw_priority_selector { -+ DPSW_UP_PCP = 0, -+ DPSW_UP_DSCP = 1 -+}; -+ -+/** -+ * enum dpsw_schedule_mode - Traffic classes scheduling -+ * @DPSW_SCHED_STRICT_PRIORITY: schedule strict priority -+ * @DPSW_SCHED_WEIGHTED: schedule based on token bucket created algorithm -+ */ -+enum dpsw_schedule_mode { -+ DPSW_SCHED_STRICT_PRIORITY, -+ DPSW_SCHED_WEIGHTED -+}; -+ -+/** -+ * struct dpsw_tx_schedule_cfg - traffic class configuration -+ * @mode: Strict or weight-based scheduling -+ * @delta_bandwidth: weighted Bandwidth in range from 100 to 10000 -+ */ -+struct dpsw_tx_schedule_cfg { -+ enum dpsw_schedule_mode mode; -+ u16 delta_bandwidth; -+}; -+ -+/** -+ * struct dpsw_tx_selection_cfg - Mapping user priority into traffic -+ * class configuration -+ * @priority_selector: Source for user priority regeneration -+ * @tc_id: The Regenerated User priority that the incoming -+ * User Priority is mapped to for this interface -+ * @tc_sched: Traffic classes configuration -+ */ -+struct dpsw_tx_selection_cfg { -+ enum dpsw_priority_selector priority_selector; -+ u8 tc_id[DPSW_MAX_PRIORITIES]; -+ struct dpsw_tx_schedule_cfg tc_sched[DPSW_MAX_TC]; -+}; -+ -+int dpsw_if_set_tx_selection(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id, -+ const struct dpsw_tx_selection_cfg *cfg); -+ -+/** -+ * enum dpsw_reflection_filter - Filter type for frames to reflect -+ * @DPSW_REFLECTION_FILTER_INGRESS_ALL: Reflect all frames -+ * @DPSW_REFLECTION_FILTER_INGRESS_VLAN: Reflect only frames belong to -+ * particular VLAN defined by vid parameter -+ * -+ */ -+enum dpsw_reflection_filter { -+ DPSW_REFLECTION_FILTER_INGRESS_ALL = 0, -+ DPSW_REFLECTION_FILTER_INGRESS_VLAN = 1 -+}; -+ -+/** -+ * struct dpsw_reflection_cfg - Structure representing reflection information -+ * @filter: Filter type for frames to reflect -+ * @vlan_id: Vlan Id to reflect; valid only when filter type is -+ * DPSW_INGRESS_VLAN -+ */ -+struct dpsw_reflection_cfg { -+ enum dpsw_reflection_filter filter; -+ u16 vlan_id; -+}; -+ -+int dpsw_if_add_reflection(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id, -+ const struct dpsw_reflection_cfg *cfg); -+ -+int dpsw_if_remove_reflection(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id, -+ const struct dpsw_reflection_cfg *cfg); -+ -+/** -+ * enum dpsw_metering_mode - Metering modes -+ * @DPSW_METERING_MODE_NONE: metering disabled -+ * @DPSW_METERING_MODE_RFC2698: RFC 2698 -+ * @DPSW_METERING_MODE_RFC4115: RFC 4115 -+ */ -+enum dpsw_metering_mode { -+ DPSW_METERING_MODE_NONE = 0, -+ DPSW_METERING_MODE_RFC2698, -+ DPSW_METERING_MODE_RFC4115 -+}; -+ -+/** -+ * enum dpsw_metering_unit - Metering count -+ * @DPSW_METERING_UNIT_BYTES: count bytes -+ * @DPSW_METERING_UNIT_FRAMES: count frames -+ */ -+enum dpsw_metering_unit { -+ DPSW_METERING_UNIT_BYTES = 0, -+ DPSW_METERING_UNIT_FRAMES -+}; -+ -+/** -+ * struct dpsw_metering_cfg - Metering configuration -+ * @mode: metering modes -+ * @units: Bytes or frame units -+ * @cir: Committed information rate (CIR) in Kbits/s -+ * @eir: Peak information rate (PIR) Kbit/s rfc2698 -+ * Excess information rate (EIR) Kbit/s rfc4115 -+ * @cbs: Committed burst size (CBS) in bytes -+ * @ebs: Peak burst size (PBS) in bytes for rfc2698 -+ * Excess bust size (EBS) in bytes rfc4115 -+ * -+ */ -+struct dpsw_metering_cfg { -+ enum dpsw_metering_mode mode; -+ enum dpsw_metering_unit units; -+ u32 cir; -+ u32 eir; -+ u32 cbs; -+ u32 ebs; -+}; -+ -+int dpsw_if_set_flooding_metering(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id, -+ const struct dpsw_metering_cfg *cfg); -+ -+int dpsw_if_set_metering(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id, -+ u8 tc_id, -+ const struct dpsw_metering_cfg *cfg); -+ -+/** -+ * enum dpsw_early_drop_unit - DPSW early drop unit -+ * @DPSW_EARLY_DROP_UNIT_BYTE: count bytes -+ * @DPSW_EARLY_DROP_UNIT_FRAMES: count frames -+ */ -+enum dpsw_early_drop_unit { -+ DPSW_EARLY_DROP_UNIT_BYTE = 0, -+ DPSW_EARLY_DROP_UNIT_FRAMES -+}; -+ -+/** -+ * enum dpsw_early_drop_mode - DPSW early drop mode -+ * @DPSW_EARLY_DROP_MODE_NONE: early drop is disabled -+ * @DPSW_EARLY_DROP_MODE_TAIL: early drop in taildrop mode -+ * @DPSW_EARLY_DROP_MODE_WRED: early drop in WRED mode -+ */ -+enum dpsw_early_drop_mode { -+ DPSW_EARLY_DROP_MODE_NONE = 0, -+ DPSW_EARLY_DROP_MODE_TAIL, -+ DPSW_EARLY_DROP_MODE_WRED -+}; -+ -+/** -+ * struct dpsw_wred_cfg - WRED configuration -+ * @max_threshold: maximum threshold that packets may be discarded. Above this -+ * threshold all packets are discarded; must be less than 2^39; -+ * approximated to be expressed as (x+256)*2^(y-1) due to HW -+ * implementation. -+ * @min_threshold: minimum threshold that packets may be discarded at -+ * @drop_probability: probability that a packet will be discarded (1-100, -+ * associated with the maximum threshold) -+ */ -+struct dpsw_wred_cfg { -+ u64 min_threshold; -+ u64 max_threshold; -+ u8 drop_probability; -+}; -+ -+/** -+ * struct dpsw_early_drop_cfg - early-drop configuration -+ * @drop_mode: drop mode -+ * @units: count units -+ * @yellow: WRED - 'yellow' configuration -+ * @green: WRED - 'green' configuration -+ * @tail_drop_threshold: tail drop threshold -+ */ -+struct dpsw_early_drop_cfg { -+ enum dpsw_early_drop_mode drop_mode; -+ enum dpsw_early_drop_unit units; -+ struct dpsw_wred_cfg yellow; -+ struct dpsw_wred_cfg green; -+ u32 tail_drop_threshold; -+}; -+ -+void dpsw_prepare_early_drop(const struct dpsw_early_drop_cfg *cfg, -+ u8 *early_drop_buf); -+ -+int dpsw_if_set_early_drop(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id, -+ u8 tc_id, -+ u64 early_drop_iova); -+ -+/** -+ * struct dpsw_custom_tpid_cfg - Structure representing tag Protocol identifier -+ * @tpid: An additional tag protocol identifier -+ */ -+struct dpsw_custom_tpid_cfg { -+ u16 tpid; -+}; -+ -+int dpsw_add_custom_tpid(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ const struct dpsw_custom_tpid_cfg *cfg); -+ -+int dpsw_remove_custom_tpid(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ const struct dpsw_custom_tpid_cfg *cfg); -+ +int dpsw_if_enable(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, @@ -14758,49 +14655,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + u16 if_id); + -+/** -+ * struct dpsw_if_attr - Structure representing DPSW interface attributes -+ * @num_tcs: Number of traffic classes -+ * @rate: Transmit rate in bits per second -+ * @options: Interface configuration options (bitmap) -+ * @enabled: Indicates if interface is enabled -+ * @accept_all_vlan: The device discards/accepts incoming frames -+ * for VLANs that do not include this interface -+ * @admit_untagged: When set to 'DPSW_ADMIT_ONLY_VLAN_TAGGED', the device -+ * discards untagged frames or priority-tagged frames received on -+ * this interface; -+ * When set to 'DPSW_ADMIT_ALL', untagged frames or priority- -+ * tagged frames received on this interface are accepted -+ * @qdid: control frames transmit qdid -+ */ -+struct dpsw_if_attr { -+ u8 num_tcs; -+ u32 rate; -+ u32 options; -+ int enabled; -+ int accept_all_vlan; -+ enum dpsw_accepted_frames admit_untagged; -+ u16 qdid; -+}; -+ -+int dpsw_if_get_attributes(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id, -+ struct dpsw_if_attr *attr); -+ +int dpsw_if_set_max_frame_length(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u16 if_id, + u16 frame_length); + -+int dpsw_if_get_max_frame_length(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 if_id, -+ u16 *frame_length); -+ +/** + * struct dpsw_vlan_cfg - VLAN Configuration + * @fdb_id: Forwarding Data Base @@ -14839,12 +14699,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 vlan_id, + const struct dpsw_vlan_if_cfg *cfg); + -+int dpsw_vlan_add_if_flooding(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 vlan_id, -+ const struct dpsw_vlan_if_cfg *cfg); -+ +int dpsw_vlan_remove_if(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, @@ -14857,77 +14711,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 vlan_id, + const struct dpsw_vlan_if_cfg *cfg); + -+int dpsw_vlan_remove_if_flooding(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 vlan_id, -+ const struct dpsw_vlan_if_cfg *cfg); -+ +int dpsw_vlan_remove(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u16 vlan_id); + +/** -+ * struct dpsw_vlan_attr - VLAN attributes -+ * @fdb_id: Associated FDB ID -+ * @num_ifs: Number of interfaces -+ * @num_untagged_ifs: Number of untagged interfaces -+ * @num_flooding_ifs: Number of flooding interfaces -+ */ -+struct dpsw_vlan_attr { -+ u16 fdb_id; -+ u16 num_ifs; -+ u16 num_untagged_ifs; -+ u16 num_flooding_ifs; -+}; -+ -+int dpsw_vlan_get_attributes(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 vlan_id, -+ struct dpsw_vlan_attr *attr); -+ -+int dpsw_vlan_get_if(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 vlan_id, -+ struct dpsw_vlan_if_cfg *cfg); -+ -+int dpsw_vlan_get_if_flooding(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 vlan_id, -+ struct dpsw_vlan_if_cfg *cfg); -+ -+int dpsw_vlan_get_if_untagged(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 vlan_id, -+ struct dpsw_vlan_if_cfg *cfg); -+ -+/** -+ * struct dpsw_fdb_cfg - FDB Configuration -+ * @num_fdb_entries: Number of FDB entries -+ * @fdb_aging_time: Aging time in seconds -+ */ -+struct dpsw_fdb_cfg { -+ u16 num_fdb_entries; -+ u16 fdb_aging_time; -+}; -+ -+int dpsw_fdb_add(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 *fdb_id, -+ const struct dpsw_fdb_cfg *cfg); -+ -+int dpsw_fdb_remove(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 fdb_id); -+ -+/** + * enum dpsw_fdb_entry_type - FDB Entry type - Static/Dynamic + * @DPSW_FDB_ENTRY_STATIC: Static entry + * @DPSW_FDB_ENTRY_DINAMIC: Dynamic entry @@ -14955,12 +14744,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 fdb_id, + const struct dpsw_fdb_unicast_cfg *cfg); + -+int dpsw_fdb_get_unicast(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 fdb_id, -+ struct dpsw_fdb_unicast_cfg *cfg); -+ +int dpsw_fdb_remove_unicast(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, @@ -14987,12 +14770,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 fdb_id, + const struct dpsw_fdb_multicast_cfg *cfg); + -+int dpsw_fdb_get_multicast(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 fdb_id, -+ struct dpsw_fdb_multicast_cfg *cfg); -+ +int dpsw_fdb_remove_multicast(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, @@ -15058,227 +14835,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 max_fdb_mc_groups; +}; + -+int dpsw_fdb_get_attributes(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 fdb_id, -+ struct dpsw_fdb_attr *attr); -+ -+/** -+ * struct dpsw_acl_cfg - ACL Configuration -+ * @max_entries: Number of FDB entries -+ */ -+struct dpsw_acl_cfg { -+ u16 max_entries; -+}; -+ -+/** -+ * struct dpsw_acl_fields - ACL fields. -+ * @l2_dest_mac: Destination MAC address: BPDU, Multicast, Broadcast, Unicast, -+ * slow protocols, MVRP, STP -+ * @l2_source_mac: Source MAC address -+ * @l2_tpid: Layer 2 (Ethernet) protocol type, used to identify the following -+ * protocols: MPLS, PTP, PFC, ARP, Jumbo frames, LLDP, IEEE802.1ae, -+ * Q-in-Q, IPv4, IPv6, PPPoE -+ * @l2_pcp_dei: indicate which protocol is encapsulated in the payload -+ * @l2_vlan_id: layer 2 VLAN ID -+ * @l2_ether_type: layer 2 Ethernet type -+ * @l3_dscp: Layer 3 differentiated services code point -+ * @l3_protocol: Tells the Network layer at the destination host, to which -+ * Protocol this packet belongs to. The following protocol are -+ * supported: ICMP, IGMP, IPv4 (encapsulation), TCP, IPv6 -+ * (encapsulation), GRE, PTP -+ * @l3_source_ip: Source IPv4 IP -+ * @l3_dest_ip: Destination IPv4 IP -+ * @l4_source_port: Source TCP/UDP Port -+ * @l4_dest_port: Destination TCP/UDP Port -+ */ -+struct dpsw_acl_fields { -+ u8 l2_dest_mac[6]; -+ u8 l2_source_mac[6]; -+ u16 l2_tpid; -+ u8 l2_pcp_dei; -+ u16 l2_vlan_id; -+ u16 l2_ether_type; -+ u8 l3_dscp; -+ u8 l3_protocol; -+ u32 l3_source_ip; -+ u32 l3_dest_ip; -+ u16 l4_source_port; -+ u16 l4_dest_port; -+}; -+ -+/** -+ * struct dpsw_acl_key - ACL key -+ * @match: Match fields -+ * @mask: Mask: b'1 - valid, b'0 don't care -+ */ -+struct dpsw_acl_key { -+ struct dpsw_acl_fields match; -+ struct dpsw_acl_fields mask; -+}; -+ -+/** -+ * enum dpsw_acl_action -+ * @DPSW_ACL_ACTION_DROP: Drop frame -+ * @DPSW_ACL_ACTION_REDIRECT: Redirect to certain port -+ * @DPSW_ACL_ACTION_ACCEPT: Accept frame -+ * @DPSW_ACL_ACTION_REDIRECT_TO_CTRL_IF: Redirect to control interface -+ */ -+enum dpsw_acl_action { -+ DPSW_ACL_ACTION_DROP, -+ DPSW_ACL_ACTION_REDIRECT, -+ DPSW_ACL_ACTION_ACCEPT, -+ DPSW_ACL_ACTION_REDIRECT_TO_CTRL_IF -+}; -+ -+/** -+ * struct dpsw_acl_result - ACL action -+ * @action: Action should be taken when ACL entry hit -+ * @if_id: Interface IDs to redirect frame. Valid only if redirect selected for -+ * action -+ */ -+struct dpsw_acl_result { -+ enum dpsw_acl_action action; -+ u16 if_id; -+}; -+ -+/** -+ * struct dpsw_acl_entry_cfg - ACL entry -+ * @key_iova: I/O virtual address of DMA-able memory filled with key after call -+ * to dpsw_acl_prepare_entry_cfg() -+ * @result: Required action when entry hit occurs -+ * @precedence: Precedence inside ACL 0 is lowest; This priority can not change -+ * during the lifetime of a Policy. It is user responsibility to -+ * space the priorities according to consequent rule additions. -+ */ -+struct dpsw_acl_entry_cfg { -+ u64 key_iova; -+ struct dpsw_acl_result result; -+ int precedence; -+}; -+ -+int dpsw_acl_add(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 *acl_id, -+ const struct dpsw_acl_cfg *cfg); -+ -+int dpsw_acl_remove(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 acl_id); -+ -+void dpsw_acl_prepare_entry_cfg(const struct dpsw_acl_key *key, -+ uint8_t *entry_cfg_buf); -+ -+int dpsw_acl_add_entry(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 acl_id, -+ const struct dpsw_acl_entry_cfg *cfg); -+ -+int dpsw_acl_remove_entry(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 acl_id, -+ const struct dpsw_acl_entry_cfg *cfg); -+ -+/** -+ * struct dpsw_acl_if_cfg - List of interfaces to Associate with ACL -+ * @num_ifs: Number of interfaces -+ * @if_id: List of interfaces -+ */ -+struct dpsw_acl_if_cfg { -+ u16 num_ifs; -+ u16 if_id[DPSW_MAX_IF]; -+}; -+ -+int dpsw_acl_add_if(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 acl_id, -+ const struct dpsw_acl_if_cfg *cfg); -+ -+int dpsw_acl_remove_if(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 acl_id, -+ const struct dpsw_acl_if_cfg *cfg); -+ -+/** -+ * struct dpsw_acl_attr - ACL Attributes -+ * @max_entries: Max number of ACL entries -+ * @num_entries: Number of used ACL entries -+ * @num_ifs: Number of interfaces associated with ACL -+ */ -+struct dpsw_acl_attr { -+ u16 max_entries; -+ u16 num_entries; -+ u16 num_ifs; -+}; -+ -+int dpsw_acl_get_attributes(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ u16 acl_id, -+ struct dpsw_acl_attr *attr); -+/** -+ * struct dpsw_ctrl_if_attr - Control interface attributes -+ * @rx_fqid: Receive FQID -+ * @rx_err_fqid: Receive error FQID -+ * @tx_err_conf_fqid: Transmit error and confirmation FQID -+ */ -+struct dpsw_ctrl_if_attr { -+ u32 rx_fqid; -+ u32 rx_err_fqid; -+ u32 tx_err_conf_fqid; -+}; -+ -+int dpsw_ctrl_if_get_attributes(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ struct dpsw_ctrl_if_attr *attr); -+ -+/** -+ * Maximum number of DPBP -+ */ -+#define DPSW_MAX_DPBP 8 -+ -+/** -+ * struct dpsw_ctrl_if_pools_cfg - Control interface buffer pools configuration -+ * @num_dpbp: Number of DPBPs -+ * @pools: Array of buffer pools parameters; The number of valid entries -+ * must match 'num_dpbp' value -+ */ -+struct dpsw_ctrl_if_pools_cfg { -+ u8 num_dpbp; -+ /** -+ * struct pools - Buffer pools parameters -+ * @dpbp_id: DPBP object ID -+ * @buffer_size: Buffer size -+ * @backup_pool: Backup pool -+ */ -+ struct { -+ int dpbp_id; -+ u16 buffer_size; -+ int backup_pool; -+ } pools[DPSW_MAX_DPBP]; -+}; -+ -+int dpsw_ctrl_if_set_pools(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token, -+ const struct dpsw_ctrl_if_pools_cfg *cfg); -+ -+int dpsw_ctrl_if_enable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token); -+ -+int dpsw_ctrl_if_disable(struct fsl_mc_io *mc_io, -+ u32 cmd_flags, -+ u16 token); -+ +int dpsw_get_api_version(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 *major_ver, @@ -15286,9 +14842,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +#endif /* __FSL_DPSW_H */ --- /dev/null -+++ b/drivers/staging/fsl-dpaa2/ethsw/switch.c -@@ -0,0 +1,1857 @@ -+/* Copyright 2014-2015 Freescale Semiconductor Inc. ++++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c +@@ -0,0 +1,206 @@ ++/* Copyright 2014-2016 Freescale Semiconductor Inc. ++ * Copyright 2017 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: @@ -15297,8 +14854,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * * Redistributions in binary form must reproduce the above copyright + * 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 ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * @@ -15307,284 +14864,363 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * 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. ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. + */ + -+#include <linux/module.h> -+#include <linux/msi.h> ++#include "ethsw.h" + -+#include <linux/netdevice.h> -+#include <linux/etherdevice.h> -+#include <linux/rtnetlink.h> -+#include <linux/if_vlan.h> -+ -+#include <uapi/linux/if_bridge.h> -+#include <net/netlink.h> ++static struct { ++ enum dpsw_counter id; ++ char name[ETH_GSTRING_LEN]; ++} ethsw_ethtool_counters[] = { ++ {DPSW_CNT_ING_FRAME, "rx frames"}, ++ {DPSW_CNT_ING_BYTE, "rx bytes"}, ++ {DPSW_CNT_ING_FLTR_FRAME, "rx filtered frames"}, ++ {DPSW_CNT_ING_FRAME_DISCARD, "rx discarded frames"}, ++ {DPSW_CNT_ING_BCAST_FRAME, "rx b-cast frames"}, ++ {DPSW_CNT_ING_BCAST_BYTES, "rx b-cast bytes"}, ++ {DPSW_CNT_ING_MCAST_FRAME, "rx m-cast frames"}, ++ {DPSW_CNT_ING_MCAST_BYTE, "rx m-cast bytes"}, ++ {DPSW_CNT_EGR_FRAME, "tx frames"}, ++ {DPSW_CNT_EGR_BYTE, "tx bytes"}, ++ {DPSW_CNT_EGR_FRAME_DISCARD, "tx discarded frames"}, + -+#include "../../fsl-mc/include/mc.h" -+#include "dpsw.h" -+#include "dpsw-cmd.h" ++}; + -+static const char ethsw_drv_version[] = "0.1"; ++#define ETHSW_NUM_COUNTERS ARRAY_SIZE(ethsw_ethtool_counters) + -+/* Minimal supported DPSE version */ -+#define DPSW_MIN_VER_MAJOR 8 -+#define DPSW_MIN_VER_MINOR 0 ++static void ethsw_get_drvinfo(struct net_device *netdev, ++ struct ethtool_drvinfo *drvinfo) ++{ ++ struct ethsw_port_priv *port_priv = netdev_priv(netdev); ++ u16 version_major, version_minor; ++ int err; + -+/* IRQ index */ -+#define DPSW_MAX_IRQ_NUM 2 ++ strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver)); + -+#define ETHSW_VLAN_MEMBER 1 -+#define ETHSW_VLAN_UNTAGGED 2 -+#define ETHSW_VLAN_PVID 4 -+#define ETHSW_VLAN_GLOBAL 8 ++ err = dpsw_get_api_version(port_priv->ethsw_data->mc_io, 0, ++ &version_major, ++ &version_minor); ++ if (err) ++ strlcpy(drvinfo->fw_version, "N/A", ++ sizeof(drvinfo->fw_version)); ++ else ++ snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), ++ "%u.%u", version_major, version_minor); + -+/* Maximum Frame Length supported by HW (currently 10k) */ -+#define DPAA2_MFL (10 * 1024) -+#define ETHSW_MAX_FRAME_LENGTH (DPAA2_MFL - VLAN_ETH_HLEN - ETH_FCS_LEN) -+#define ETHSW_L2_MAX_FRM(mtu) ((mtu) + VLAN_ETH_HLEN + ETH_FCS_LEN) ++ strlcpy(drvinfo->bus_info, dev_name(netdev->dev.parent->parent), ++ sizeof(drvinfo->bus_info)); ++} + -+struct ethsw_port_priv { -+ struct net_device *netdev; -+ struct list_head list; -+ u16 port_index; -+ struct ethsw_dev_priv *ethsw_priv; -+ u8 stp_state; ++static int ++ethsw_get_link_ksettings(struct net_device *netdev, ++ struct ethtool_link_ksettings *link_ksettings) ++{ ++ struct ethsw_port_priv *port_priv = netdev_priv(netdev); ++ struct dpsw_link_state state = {0}; ++ int err = 0; + -+ char vlans[VLAN_VID_MASK + 1]; ++ err = dpsw_if_get_link_state(port_priv->ethsw_data->mc_io, 0, ++ port_priv->ethsw_data->dpsw_handle, ++ port_priv->idx, ++ &state); ++ if (err) { ++ netdev_err(netdev, "ERROR %d getting link state", err); ++ goto out; ++ } + -+}; ++ /* At the moment, we have no way of interrogating the DPMAC ++ * from the DPSW side or there may not exist a DPMAC at all. ++ * Report only autoneg state, duplexity and speed. ++ */ ++ if (state.options & DPSW_LINK_OPT_AUTONEG) ++ link_ksettings->base.autoneg = AUTONEG_ENABLE; ++ if (!(state.options & DPSW_LINK_OPT_HALF_DUPLEX)) ++ link_ksettings->base.duplex = DUPLEX_FULL; ++ link_ksettings->base.speed = state.rate; + -+struct ethsw_dev_priv { -+ struct net_device *netdev; -+ struct fsl_mc_io *mc_io; -+ u16 dpsw_handle; -+ struct dpsw_attr sw_attr; -+ int dev_id; -+ /*TODO: redundant, we can use the slave dev list */ -+ struct list_head port_list; ++out: ++ return err; ++} + -+ bool flood; -+ bool learning; ++static int ++ethsw_set_link_ksettings(struct net_device *netdev, ++ const struct ethtool_link_ksettings *link_ksettings) ++{ ++ struct ethsw_port_priv *port_priv = netdev_priv(netdev); ++ struct dpsw_link_cfg cfg = {0}; ++ int err = 0; + -+ char vlans[VLAN_VID_MASK + 1]; -+}; ++ netdev_dbg(netdev, "Setting link parameters..."); + -+static int ethsw_port_stop(struct net_device *netdev); -+static int ethsw_port_open(struct net_device *netdev); ++ /* Due to a temporary MC limitation, the DPSW port must be down ++ * in order to be able to change link settings. Taking steps to let ++ * the user know that. ++ */ ++ if (netif_running(netdev)) { ++ netdev_info(netdev, "Sorry, interface must be brought down first.\n"); ++ return -EACCES; ++ } + -+static inline void __get_priv(struct net_device *netdev, -+ struct ethsw_dev_priv **priv, -+ struct ethsw_port_priv **port_priv) -+{ -+ struct ethsw_dev_priv *_priv = NULL; -+ struct ethsw_port_priv *_port_priv = NULL; ++ cfg.rate = link_ksettings->base.speed; ++ if (link_ksettings->base.autoneg == AUTONEG_ENABLE) ++ cfg.options |= DPSW_LINK_OPT_AUTONEG; ++ else ++ cfg.options &= ~DPSW_LINK_OPT_AUTONEG; ++ if (link_ksettings->base.duplex == DUPLEX_HALF) ++ cfg.options |= DPSW_LINK_OPT_HALF_DUPLEX; ++ else ++ cfg.options &= ~DPSW_LINK_OPT_HALF_DUPLEX; + -+ if (netdev->flags & IFF_MASTER) { -+ _priv = netdev_priv(netdev); -+ } else { -+ _port_priv = netdev_priv(netdev); -+ _priv = _port_priv->ethsw_priv; -+ } ++ err = dpsw_if_set_link_cfg(port_priv->ethsw_data->mc_io, 0, ++ port_priv->ethsw_data->dpsw_handle, ++ port_priv->idx, ++ &cfg); ++ if (err) ++ /* ethtool will be loud enough if we return an error; no point ++ * in putting our own error message on the console by default ++ */ ++ netdev_dbg(netdev, "ERROR %d setting link cfg", err); + -+ if (priv) -+ *priv = _priv; -+ if (port_priv) -+ *port_priv = _port_priv; ++ return err; +} + -+/* -------------------------------------------------------------------------- */ -+/* ethsw netdevice ops */ -+ -+static netdev_tx_t ethsw_dropframe(struct sk_buff *skb, struct net_device *dev) ++static int ethsw_ethtool_get_sset_count(struct net_device *dev, int sset) +{ -+ /* we don't support I/O for now, drop the frame */ -+ dev_kfree_skb_any(skb); -+ return NETDEV_TX_OK; ++ switch (sset) { ++ case ETH_SS_STATS: ++ return ETHSW_NUM_COUNTERS; ++ default: ++ return -EOPNOTSUPP; ++ } +} + -+static int ethsw_open(struct net_device *netdev) ++static void ethsw_ethtool_get_strings(struct net_device *netdev, ++ u32 stringset, u8 *data) +{ -+ struct ethsw_dev_priv *priv = netdev_priv(netdev); -+ struct list_head *pos; -+ struct ethsw_port_priv *port_priv = NULL; -+ int err; -+ -+ err = dpsw_enable(priv->mc_io, 0, priv->dpsw_handle); -+ if (err) { -+ netdev_err(netdev, "dpsw_enable err %d\n", err); -+ return err; -+ } ++ int i; + -+ list_for_each(pos, &priv->port_list) { -+ port_priv = list_entry(pos, struct ethsw_port_priv, list); -+ err = dev_open(port_priv->netdev); -+ if (err) -+ netdev_err(port_priv->netdev, "dev_open err %d\n", err); ++ switch (stringset) { ++ case ETH_SS_STATS: ++ for (i = 0; i < ETHSW_NUM_COUNTERS; i++) ++ memcpy(data + i * ETH_GSTRING_LEN, ++ ethsw_ethtool_counters[i].name, ETH_GSTRING_LEN); ++ break; + } -+ -+ return 0; +} + -+static int ethsw_stop(struct net_device *netdev) ++static void ethsw_ethtool_get_stats(struct net_device *netdev, ++ struct ethtool_stats *stats, ++ u64 *data) +{ -+ struct ethsw_dev_priv *priv = netdev_priv(netdev); -+ struct list_head *pos; -+ struct ethsw_port_priv *port_priv = NULL; -+ int err; ++ struct ethsw_port_priv *port_priv = netdev_priv(netdev); ++ int i, err; + -+ err = dpsw_disable(priv->mc_io, 0, priv->dpsw_handle); -+ if (err) { -+ netdev_err(netdev, "dpsw_disable err %d\n", err); -+ return err; -+ } ++ memset(data, 0, ++ sizeof(u64) * ETHSW_NUM_COUNTERS); + -+ list_for_each(pos, &priv->port_list) { -+ port_priv = list_entry(pos, struct ethsw_port_priv, list); -+ err = dev_close(port_priv->netdev); ++ for (i = 0; i < ETHSW_NUM_COUNTERS; i++) { ++ err = dpsw_if_get_counter(port_priv->ethsw_data->mc_io, 0, ++ port_priv->ethsw_data->dpsw_handle, ++ port_priv->idx, ++ ethsw_ethtool_counters[i].id, ++ &data[i]); + if (err) -+ netdev_err(port_priv->netdev, -+ "dev_close err %d\n", err); ++ netdev_err(netdev, "dpsw_if_get_counter[%s] err %d\n", ++ ethsw_ethtool_counters[i].name, err); + } -+ -+ return 0; +} + -+static int ethsw_add_vlan(struct net_device *netdev, u16 vid) ++const struct ethtool_ops ethsw_port_ethtool_ops = { ++ .get_drvinfo = ethsw_get_drvinfo, ++ .get_link = ethtool_op_get_link, ++ .get_link_ksettings = ethsw_get_link_ksettings, ++ .set_link_ksettings = ethsw_set_link_ksettings, ++ .get_strings = ethsw_ethtool_get_strings, ++ .get_ethtool_stats = ethsw_ethtool_get_stats, ++ .get_sset_count = ethsw_ethtool_get_sset_count, ++}; +--- /dev/null ++++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +@@ -0,0 +1,1438 @@ ++/* Copyright 2014-2016 Freescale Semiconductor Inc. ++ * Copyright 2017 NXP ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include <linux/module.h> ++ ++#include <linux/interrupt.h> ++#include <linux/msi.h> ++#include <linux/kthread.h> ++#include <linux/workqueue.h> ++ ++#include <linux/fsl/mc.h> ++ ++#include "ethsw.h" ++ ++static struct workqueue_struct *ethsw_owq; ++ ++/* Minimal supported DPSW version */ ++#define DPSW_MIN_VER_MAJOR 8 ++#define DPSW_MIN_VER_MINOR 0 ++ ++#define DEFAULT_VLAN_ID 1 ++ ++static int ethsw_add_vlan(struct ethsw_core *ethsw, u16 vid) +{ -+ struct ethsw_dev_priv *priv = netdev_priv(netdev); -+ int err; ++ int err; + + struct dpsw_vlan_cfg vcfg = { -+ /* TODO: add support for VLAN private FDBs */ + .fdb_id = 0, + }; -+ if (priv->vlans[vid]) { -+ netdev_err(netdev, "VLAN already configured\n"); ++ ++ if (ethsw->vlans[vid]) { ++ dev_err(ethsw->dev, "VLAN already configured\n"); + return -EEXIST; + } + -+ err = dpsw_vlan_add(priv->mc_io, 0, priv->dpsw_handle, vid, &vcfg); ++ err = dpsw_vlan_add(ethsw->mc_io, 0, ++ ethsw->dpsw_handle, vid, &vcfg); + if (err) { -+ netdev_err(netdev, "dpsw_vlan_add err %d\n", err); ++ dev_err(ethsw->dev, "dpsw_vlan_add err %d\n", err); + return err; + } -+ priv->vlans[vid] = ETHSW_VLAN_MEMBER; ++ ethsw->vlans[vid] = ETHSW_VLAN_MEMBER; + + return 0; +} + -+static int ethsw_port_add_vlan(struct net_device *netdev, u16 vid, u16 flags) ++static int ethsw_port_set_pvid(struct ethsw_port_priv *port_priv, u16 pvid) +{ -+ struct ethsw_port_priv *port_priv = netdev_priv(netdev); -+ struct ethsw_dev_priv *priv = port_priv->ethsw_priv; -+ int err; -+ -+ struct dpsw_vlan_if_cfg vcfg = { -+ .num_ifs = 1, -+ .if_id[0] = port_priv->port_index, -+ }; -+ -+ if (port_priv->vlans[vid]) { -+ netdev_err(netdev, "VLAN already configured\n"); -+ return -EEXIST; -+ } ++ struct ethsw_core *ethsw = port_priv->ethsw_data; ++ struct net_device *netdev = port_priv->netdev; ++ struct dpsw_tci_cfg tci_cfg = { 0 }; ++ bool is_oper; ++ int err, ret; + -+ if (flags & BRIDGE_VLAN_INFO_PVID && netif_oper_up(netdev)) { -+ netdev_err(netdev, "interface must be down to change PVID!\n"); -+ return -EBUSY; -+ } -+ -+ err = dpsw_vlan_add_if(priv->mc_io, 0, priv->dpsw_handle, vid, &vcfg); ++ err = dpsw_if_get_tci(ethsw->mc_io, 0, ethsw->dpsw_handle, ++ port_priv->idx, &tci_cfg); + if (err) { -+ netdev_err(netdev, "dpsw_vlan_add_if err %d\n", err); ++ netdev_err(netdev, "dpsw_if_get_tci err %d\n", err); + return err; + } -+ port_priv->vlans[vid] = ETHSW_VLAN_MEMBER; + -+ if (flags & BRIDGE_VLAN_INFO_UNTAGGED) { -+ err = dpsw_vlan_add_if_untagged(priv->mc_io, 0, -+ priv->dpsw_handle, vid, &vcfg); ++ tci_cfg.vlan_id = pvid; ++ ++ /* Interface needs to be down to change PVID */ ++ is_oper = netif_oper_up(netdev); ++ if (is_oper) { ++ err = dpsw_if_disable(ethsw->mc_io, 0, ++ ethsw->dpsw_handle, ++ port_priv->idx); + if (err) { -+ netdev_err(netdev, "dpsw_vlan_add_if_untagged err %d\n", -+ err); ++ netdev_err(netdev, "dpsw_if_disable err %d\n", err); + return err; + } -+ port_priv->vlans[vid] |= ETHSW_VLAN_UNTAGGED; + } + -+ if (flags & BRIDGE_VLAN_INFO_PVID) { -+ struct dpsw_tci_cfg tci_cfg = { -+ /* TODO: at least add better defaults if these cannot -+ * be configured -+ */ -+ .pcp = 0, -+ .dei = 0, -+ .vlan_id = vid, -+ }; -+ -+ err = dpsw_if_set_tci(priv->mc_io, 0, priv->dpsw_handle, -+ port_priv->port_index, &tci_cfg); -+ if (err) { -+ netdev_err(netdev, "dpsw_if_set_tci err %d\n", err); -+ return err; ++ err = dpsw_if_set_tci(ethsw->mc_io, 0, ethsw->dpsw_handle, ++ port_priv->idx, &tci_cfg); ++ if (err) { ++ netdev_err(netdev, "dpsw_if_set_tci err %d\n", err); ++ goto set_tci_error; ++ } ++ ++ /* Delete previous PVID info and mark the new one */ ++ port_priv->vlans[port_priv->pvid] &= ~ETHSW_VLAN_PVID; ++ port_priv->vlans[pvid] |= ETHSW_VLAN_PVID; ++ port_priv->pvid = pvid; ++ ++set_tci_error: ++ if (is_oper) { ++ ret = dpsw_if_enable(ethsw->mc_io, 0, ++ ethsw->dpsw_handle, ++ port_priv->idx); ++ if (ret) { ++ netdev_err(netdev, "dpsw_if_enable err %d\n", ret); ++ return ret; + } -+ port_priv->vlans[vid] |= ETHSW_VLAN_PVID; + } + -+ return 0; ++ return err; +} + -+static const struct nla_policy ifla_br_policy[IFLA_MAX + 1] = { -+ [IFLA_BRIDGE_FLAGS] = { .type = NLA_U16 }, -+ [IFLA_BRIDGE_MODE] = { .type = NLA_U16 }, -+ [IFLA_BRIDGE_VLAN_INFO] = { .type = NLA_BINARY, -+ .len = sizeof(struct bridge_vlan_info), }, -+}; -+ -+static int ethsw_setlink_af_spec(struct net_device *netdev, -+ struct nlattr **tb) ++static int ethsw_port_add_vlan(struct ethsw_port_priv *port_priv, ++ u16 vid, u16 flags) +{ -+ struct bridge_vlan_info *vinfo; -+ struct ethsw_dev_priv *priv = NULL; -+ struct ethsw_port_priv *port_priv = NULL; -+ int err = 0; ++ struct ethsw_core *ethsw = port_priv->ethsw_data; ++ struct net_device *netdev = port_priv->netdev; ++ struct dpsw_vlan_if_cfg vcfg; ++ int err; + -+ if (!tb[IFLA_BRIDGE_VLAN_INFO]) { -+ netdev_err(netdev, "no VLAN INFO in nlmsg\n"); -+ return -EOPNOTSUPP; ++ if (port_priv->vlans[vid]) { ++ netdev_warn(netdev, "VLAN %d already configured\n", vid); ++ return -EEXIST; + } + -+ vinfo = nla_data(tb[IFLA_BRIDGE_VLAN_INFO]); -+ -+ if (!vinfo->vid || vinfo->vid > VLAN_VID_MASK) -+ return -EINVAL; ++ vcfg.num_ifs = 1; ++ vcfg.if_id[0] = port_priv->idx; ++ err = dpsw_vlan_add_if(ethsw->mc_io, 0, ethsw->dpsw_handle, vid, &vcfg); ++ if (err) { ++ netdev_err(netdev, "dpsw_vlan_add_if err %d\n", err); ++ return err; ++ } + -+ __get_priv(netdev, &priv, &port_priv); ++ port_priv->vlans[vid] = ETHSW_VLAN_MEMBER; + -+ if (!port_priv || !priv->vlans[vinfo->vid]) { -+ /* command targets switch device or this is a new VLAN */ -+ err = ethsw_add_vlan(priv->netdev, vinfo->vid); -+ if (err) ++ if (flags & BRIDGE_VLAN_INFO_UNTAGGED) { ++ err = dpsw_vlan_add_if_untagged(ethsw->mc_io, 0, ++ ethsw->dpsw_handle, ++ vid, &vcfg); ++ if (err) { ++ netdev_err(netdev, ++ "dpsw_vlan_add_if_untagged err %d\n", err); + return err; -+ -+ /* command targets switch device; mark it*/ -+ if (!port_priv) -+ priv->vlans[vinfo->vid] |= ETHSW_VLAN_GLOBAL; ++ } ++ port_priv->vlans[vid] |= ETHSW_VLAN_UNTAGGED; + } + -+ if (port_priv) { -+ /* command targets switch port */ -+ err = ethsw_port_add_vlan(netdev, vinfo->vid, vinfo->flags); ++ if (flags & BRIDGE_VLAN_INFO_PVID) { ++ err = ethsw_port_set_pvid(port_priv, vid); + if (err) + return err; + } @@ -15592,1263 +15228,941 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return 0; +} + -+static const struct nla_policy ifla_brport_policy[IFLA_BRPORT_MAX + 1] = { -+ [IFLA_BRPORT_STATE] = { .type = NLA_U8 }, -+ [IFLA_BRPORT_COST] = { .type = NLA_U32 }, -+ [IFLA_BRPORT_PRIORITY] = { .type = NLA_U16 }, -+ [IFLA_BRPORT_MODE] = { .type = NLA_U8 }, -+ [IFLA_BRPORT_GUARD] = { .type = NLA_U8 }, -+ [IFLA_BRPORT_PROTECT] = { .type = NLA_U8 }, -+ [IFLA_BRPORT_LEARNING] = { .type = NLA_U8 }, -+ [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 }, -+}; -+ -+static int ethsw_set_learning(struct net_device *netdev, u8 flag) ++static int ethsw_set_learning(struct ethsw_core *ethsw, u8 flag) +{ -+ struct ethsw_dev_priv *priv = netdev_priv(netdev); -+ enum dpsw_fdb_learning_mode learn_mode; -+ int err; ++ enum dpsw_fdb_learning_mode learn_mode; ++ int err; + + if (flag) + learn_mode = DPSW_FDB_LEARNING_MODE_HW; + else + learn_mode = DPSW_FDB_LEARNING_MODE_DIS; + -+ err = dpsw_fdb_set_learning_mode(priv->mc_io, 0, priv->dpsw_handle, -+ 0, learn_mode); ++ err = dpsw_fdb_set_learning_mode(ethsw->mc_io, 0, ethsw->dpsw_handle, 0, ++ learn_mode); + if (err) { -+ netdev_err(netdev, "dpsw_fdb_set_learning_mode err %d\n", err); ++ dev_err(ethsw->dev, "dpsw_fdb_set_learning_mode err %d\n", err); + return err; + } -+ priv->learning = !!flag; ++ ethsw->learning = !!flag; + + return 0; +} + -+static int ethsw_port_set_flood(struct net_device *netdev, u8 flag) ++static int ethsw_port_set_flood(struct ethsw_port_priv *port_priv, u8 flag) +{ -+ struct ethsw_port_priv *port_priv = netdev_priv(netdev); -+ struct ethsw_dev_priv *priv = port_priv->ethsw_priv; -+ int err; ++ int err; + -+ err = dpsw_if_set_flooding(priv->mc_io, 0, priv->dpsw_handle, -+ port_priv->port_index, (int)flag); ++ err = dpsw_if_set_flooding(port_priv->ethsw_data->mc_io, 0, ++ port_priv->ethsw_data->dpsw_handle, ++ port_priv->idx, flag); + if (err) { -+ netdev_err(netdev, "dpsw_fdb_set_learning_mode err %d\n", err); ++ netdev_err(port_priv->netdev, ++ "dpsw_fdb_set_learning_mode err %d\n", err); + return err; + } -+ priv->flood = !!flag; ++ port_priv->flood = !!flag; + + return 0; +} + -+static int ethsw_port_set_state(struct net_device *netdev, u8 state) ++static int ethsw_port_set_stp_state(struct ethsw_port_priv *port_priv, u8 state) +{ -+ struct ethsw_port_priv *port_priv = netdev_priv(netdev); -+ struct ethsw_dev_priv *priv = port_priv->ethsw_priv; -+ u8 old_state = port_priv->stp_state; -+ int err; -+ + struct dpsw_stp_cfg stp_cfg = { -+ .vlan_id = 1, ++ .vlan_id = DEFAULT_VLAN_ID, + .state = state, + }; -+ /* TODO: check port state, interface may be down */ -+ -+ if (state > BR_STATE_BLOCKING) -+ return -EINVAL; -+ -+ if (state == port_priv->stp_state) -+ return 0; -+ -+ if (state == BR_STATE_DISABLED) { -+ port_priv->stp_state = state; -+ -+ err = ethsw_port_stop(netdev); -+ if (err) -+ goto error; -+ } else { -+ err = dpsw_if_set_stp(priv->mc_io, 0, priv->dpsw_handle, -+ port_priv->port_index, &stp_cfg); -+ if (err) { -+ netdev_err(netdev, "dpsw_if_set_stp err %d\n", err); -+ return err; -+ } ++ int err; + -+ port_priv->stp_state = state; ++ if (!netif_oper_up(port_priv->netdev) || state == port_priv->stp_state) ++ return 0; /* Nothing to do */ + -+ if (old_state == BR_STATE_DISABLED) { -+ err = ethsw_port_open(netdev); -+ if (err) -+ goto error; -+ } ++ err = dpsw_if_set_stp(port_priv->ethsw_data->mc_io, 0, ++ port_priv->ethsw_data->dpsw_handle, ++ port_priv->idx, &stp_cfg); ++ if (err) { ++ netdev_err(port_priv->netdev, ++ "dpsw_if_set_stp err %d\n", err); ++ return err; + } + ++ port_priv->stp_state = state; ++ + return 0; -+error: -+ port_priv->stp_state = old_state; -+ return err; +} + -+static int ethsw_setlink_protinfo(struct net_device *netdev, -+ struct nlattr **tb) ++static int ethsw_dellink_switch(struct ethsw_core *ethsw, u16 vid) +{ -+ struct ethsw_dev_priv *priv; -+ struct ethsw_port_priv *port_priv = NULL; -+ int err = 0; -+ -+ __get_priv(netdev, &priv, &port_priv); -+ -+ if (tb[IFLA_BRPORT_LEARNING]) { -+ u8 flag = nla_get_u8(tb[IFLA_BRPORT_LEARNING]); -+ -+ if (port_priv) -+ netdev_warn(netdev, -+ "learning set on whole switch dev\n"); -+ -+ err = ethsw_set_learning(priv->netdev, flag); -+ if (err) -+ return err; -+ -+ } else if (tb[IFLA_BRPORT_UNICAST_FLOOD] && port_priv) { -+ u8 flag = nla_get_u8(tb[IFLA_BRPORT_UNICAST_FLOOD]); -+ -+ err = ethsw_port_set_flood(port_priv->netdev, flag); -+ if (err) -+ return err; ++ struct ethsw_port_priv *ppriv_local = NULL; ++ int i, err; + -+ } else if (tb[IFLA_BRPORT_STATE] && port_priv) { -+ u8 state = nla_get_u8(tb[IFLA_BRPORT_STATE]); ++ if (!ethsw->vlans[vid]) ++ return -ENOENT; + -+ err = ethsw_port_set_state(port_priv->netdev, state); -+ if (err) -+ return err; ++ err = dpsw_vlan_remove(ethsw->mc_io, 0, ethsw->dpsw_handle, vid); ++ if (err) { ++ dev_err(ethsw->dev, "dpsw_vlan_remove err %d\n", err); ++ return err; ++ } ++ ethsw->vlans[vid] = 0; + -+ } else { -+ return -EOPNOTSUPP; ++ for (i = 0; i < ethsw->sw_attr.num_ifs; i++) { ++ ppriv_local = ethsw->ports[i]; ++ ppriv_local->vlans[vid] = 0; + } + + return 0; +} + -+static int ethsw_setlink(struct net_device *netdev, -+ struct nlmsghdr *nlh, -+ u16 flags) ++static int ethsw_port_fdb_add_uc(struct ethsw_port_priv *port_priv, ++ const unsigned char *addr) +{ -+ struct nlattr *attr; -+ struct nlattr *tb[(IFLA_BRIDGE_MAX > IFLA_BRPORT_MAX) ? -+ IFLA_BRIDGE_MAX : IFLA_BRPORT_MAX + 1]; -+ int err = 0; ++ struct dpsw_fdb_unicast_cfg entry = {0}; ++ int err; + -+ attr = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC); -+ if (attr) { -+ err = nla_parse_nested(tb, IFLA_BRIDGE_MAX, attr, -+ ifla_br_policy); -+ if (err) { -+ netdev_err(netdev, -+ "nla_parse_nested for br_policy err %d\n", -+ err); -+ return err; -+ } ++ entry.if_egress = port_priv->idx; ++ entry.type = DPSW_FDB_ENTRY_STATIC; ++ ether_addr_copy(entry.mac_addr, addr); + -+ err = ethsw_setlink_af_spec(netdev, tb); -+ return err; -+ } ++ err = dpsw_fdb_add_unicast(port_priv->ethsw_data->mc_io, 0, ++ port_priv->ethsw_data->dpsw_handle, ++ 0, &entry); ++ if (err) ++ netdev_err(port_priv->netdev, ++ "dpsw_fdb_add_unicast err %d\n", err); ++ return err; ++} + -+ attr = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_PROTINFO); -+ if (attr) { -+ err = nla_parse_nested(tb, IFLA_BRPORT_MAX, attr, -+ ifla_brport_policy); -+ if (err) { -+ netdev_err(netdev, -+ "nla_parse_nested for brport_policy err %d\n", -+ err); -+ return err; -+ } ++static int ethsw_port_fdb_del_uc(struct ethsw_port_priv *port_priv, ++ const unsigned char *addr) ++{ ++ struct dpsw_fdb_unicast_cfg entry = {0}; ++ int err; + -+ err = ethsw_setlink_protinfo(netdev, tb); -+ return err; -+ } ++ entry.if_egress = port_priv->idx; ++ entry.type = DPSW_FDB_ENTRY_STATIC; ++ ether_addr_copy(entry.mac_addr, addr); + -+ netdev_err(netdev, "nlmsg_find_attr found no AF_SPEC/PROTINFO\n"); -+ return -EOPNOTSUPP; ++ err = dpsw_fdb_remove_unicast(port_priv->ethsw_data->mc_io, 0, ++ port_priv->ethsw_data->dpsw_handle, ++ 0, &entry); ++ /* Silently discard calling multiple times the del command */ ++ if (err && err != -ENXIO) ++ netdev_err(port_priv->netdev, ++ "dpsw_fdb_remove_unicast err %d\n", err); ++ return err; +} + -+static int __nla_put_netdev(struct sk_buff *skb, struct net_device *netdev, -+ struct ethsw_dev_priv *priv) ++static int ethsw_port_fdb_add_mc(struct ethsw_port_priv *port_priv, ++ const unsigned char *addr) +{ -+ u8 operstate = netif_running(netdev) ? netdev->operstate : IF_OPER_DOWN; -+ int iflink; ++ struct dpsw_fdb_multicast_cfg entry = {0}; + int err; + -+ err = nla_put_string(skb, IFLA_IFNAME, netdev->name); -+ if (err) -+ goto nla_put_err; -+ err = nla_put_u32(skb, IFLA_MASTER, priv->netdev->ifindex); -+ if (err) -+ goto nla_put_err; -+ err = nla_put_u32(skb, IFLA_MTU, netdev->mtu); -+ if (err) -+ goto nla_put_err; -+ err = nla_put_u8(skb, IFLA_OPERSTATE, operstate); -+ if (err) -+ goto nla_put_err; -+ if (netdev->addr_len) { -+ err = nla_put(skb, IFLA_ADDRESS, netdev->addr_len, -+ netdev->dev_addr); -+ if (err) -+ goto nla_put_err; -+ } -+ -+ iflink = dev_get_iflink(netdev); -+ if (netdev->ifindex != iflink) { -+ err = nla_put_u32(skb, IFLA_LINK, iflink); -+ if (err) -+ goto nla_put_err; -+ } -+ -+ return 0; ++ ether_addr_copy(entry.mac_addr, addr); ++ entry.type = DPSW_FDB_ENTRY_STATIC; ++ entry.num_ifs = 1; ++ entry.if_id[0] = port_priv->idx; + -+nla_put_err: -+ netdev_err(netdev, "nla_put_ err %d\n", err); ++ err = dpsw_fdb_add_multicast(port_priv->ethsw_data->mc_io, 0, ++ port_priv->ethsw_data->dpsw_handle, ++ 0, &entry); ++ /* Silently discard calling multiple times the add command */ ++ if (err && err != -ENXIO) ++ netdev_err(port_priv->netdev, "dpsw_fdb_add_multicast err %d\n", ++ err); + return err; +} + -+static int __nla_put_port(struct sk_buff *skb, struct net_device *netdev, -+ struct ethsw_port_priv *port_priv) ++static int ethsw_port_fdb_del_mc(struct ethsw_port_priv *port_priv, ++ const unsigned char *addr) +{ -+ struct nlattr *nest; ++ struct dpsw_fdb_multicast_cfg entry = {0}; + int err; + -+ u8 stp_state = port_priv->stp_state; ++ ether_addr_copy(entry.mac_addr, addr); ++ entry.type = DPSW_FDB_ENTRY_STATIC; ++ entry.num_ifs = 1; ++ entry.if_id[0] = port_priv->idx; + -+ if (port_priv->stp_state == DPSW_STP_STATE_BLOCKING) -+ stp_state = BR_STATE_BLOCKING; ++ err = dpsw_fdb_remove_multicast(port_priv->ethsw_data->mc_io, 0, ++ port_priv->ethsw_data->dpsw_handle, ++ 0, &entry); ++ /* Silently discard calling multiple times the del command */ ++ if (err && err != -ENAVAIL) ++ netdev_err(port_priv->netdev, ++ "dpsw_fdb_remove_multicast err %d\n", err); ++ return err; ++} + -+ nest = nla_nest_start(skb, IFLA_PROTINFO | NLA_F_NESTED); -+ if (!nest) { -+ netdev_err(netdev, "nla_nest_start failed\n"); -+ return -ENOMEM; -+ } ++static void port_get_stats(struct net_device *netdev, ++ struct rtnl_link_stats64 *stats) ++{ ++ struct ethsw_port_priv *port_priv = netdev_priv(netdev); ++ u64 tmp; ++ int err; + -+ err = nla_put_u8(skb, IFLA_BRPORT_STATE, stp_state); -+ if (err) -+ goto nla_put_err; -+ err = nla_put_u16(skb, IFLA_BRPORT_PRIORITY, 0); ++ err = dpsw_if_get_counter(port_priv->ethsw_data->mc_io, 0, ++ port_priv->ethsw_data->dpsw_handle, ++ port_priv->idx, ++ DPSW_CNT_ING_FRAME, &stats->rx_packets); + if (err) -+ goto nla_put_err; -+ err = nla_put_u32(skb, IFLA_BRPORT_COST, 0); -+ if (err) -+ goto nla_put_err; -+ err = nla_put_u8(skb, IFLA_BRPORT_MODE, 0); ++ goto error; ++ ++ err = dpsw_if_get_counter(port_priv->ethsw_data->mc_io, 0, ++ port_priv->ethsw_data->dpsw_handle, ++ port_priv->idx, ++ DPSW_CNT_EGR_FRAME, &stats->tx_packets); + if (err) -+ goto nla_put_err; -+ err = nla_put_u8(skb, IFLA_BRPORT_GUARD, 0); ++ goto error; ++ ++ err = dpsw_if_get_counter(port_priv->ethsw_data->mc_io, 0, ++ port_priv->ethsw_data->dpsw_handle, ++ port_priv->idx, ++ DPSW_CNT_ING_BYTE, &stats->rx_bytes); + if (err) -+ goto nla_put_err; -+ err = nla_put_u8(skb, IFLA_BRPORT_PROTECT, 0); ++ goto error; ++ ++ err = dpsw_if_get_counter(port_priv->ethsw_data->mc_io, 0, ++ port_priv->ethsw_data->dpsw_handle, ++ port_priv->idx, ++ DPSW_CNT_EGR_BYTE, &stats->tx_bytes); + if (err) -+ goto nla_put_err; -+ err = nla_put_u8(skb, IFLA_BRPORT_FAST_LEAVE, 0); ++ goto error; ++ ++ err = dpsw_if_get_counter(port_priv->ethsw_data->mc_io, 0, ++ port_priv->ethsw_data->dpsw_handle, ++ port_priv->idx, ++ DPSW_CNT_ING_FRAME_DISCARD, ++ &stats->rx_dropped); + if (err) -+ goto nla_put_err; -+ err = nla_put_u8(skb, IFLA_BRPORT_LEARNING, -+ port_priv->ethsw_priv->learning); ++ goto error; ++ ++ err = dpsw_if_get_counter(port_priv->ethsw_data->mc_io, 0, ++ port_priv->ethsw_data->dpsw_handle, ++ port_priv->idx, ++ DPSW_CNT_ING_FLTR_FRAME, ++ &tmp); + if (err) -+ goto nla_put_err; -+ err = nla_put_u8(skb, IFLA_BRPORT_UNICAST_FLOOD, -+ port_priv->ethsw_priv->flood); ++ goto error; ++ stats->rx_dropped += tmp; ++ ++ err = dpsw_if_get_counter(port_priv->ethsw_data->mc_io, 0, ++ port_priv->ethsw_data->dpsw_handle, ++ port_priv->idx, ++ DPSW_CNT_EGR_FRAME_DISCARD, ++ &stats->tx_dropped); + if (err) -+ goto nla_put_err; -+ nla_nest_end(skb, nest); ++ goto error; + -+ return 0; ++ return; + -+nla_put_err: -+ netdev_err(netdev, "nla_put_ err %d\n", err); -+ nla_nest_cancel(skb, nest); -+ return err; ++error: ++ netdev_err(netdev, "dpsw_if_get_counter err %d\n", err); +} + -+static int __nla_put_vlan(struct sk_buff *skb, struct net_device *netdev, -+ struct ethsw_dev_priv *priv, -+ struct ethsw_port_priv *port_priv) ++static bool port_has_offload_stats(const struct net_device *netdev, ++ int attr_id) +{ -+ struct nlattr *nest; -+ struct bridge_vlan_info vinfo; -+ const char *vlans; -+ u16 i; -+ int err; ++ return (attr_id == IFLA_OFFLOAD_XSTATS_CPU_HIT); ++} + -+ nest = nla_nest_start(skb, IFLA_AF_SPEC); -+ if (!nest) { -+ netdev_err(netdev, "nla_nest_start failed"); -+ return -ENOMEM; ++static int port_get_offload_stats(int attr_id, ++ const struct net_device *netdev, ++ void *sp) ++{ ++ switch (attr_id) { ++ case IFLA_OFFLOAD_XSTATS_CPU_HIT: ++ port_get_stats((struct net_device *)netdev, sp); ++ return 0; + } + -+ if (port_priv) -+ vlans = port_priv->vlans; -+ else -+ vlans = priv->vlans; -+ -+ for (i = 0; i < VLAN_VID_MASK + 1; i++) { -+ vinfo.flags = 0; -+ vinfo.vid = i; -+ -+ if (vlans[i] & ETHSW_VLAN_UNTAGGED) -+ vinfo.flags |= BRIDGE_VLAN_INFO_UNTAGGED; ++ return -EINVAL; ++} + -+ if (vlans[i] & ETHSW_VLAN_PVID) -+ vinfo.flags |= BRIDGE_VLAN_INFO_PVID; ++static int port_change_mtu(struct net_device *netdev, int mtu) ++{ ++ struct ethsw_port_priv *port_priv = netdev_priv(netdev); ++ int err; + -+ if (vlans[i] & ETHSW_VLAN_MEMBER) { -+ err = nla_put(skb, IFLA_BRIDGE_VLAN_INFO, -+ sizeof(vinfo), &vinfo); -+ if (err) -+ goto nla_put_err; -+ } ++ err = dpsw_if_set_max_frame_length(port_priv->ethsw_data->mc_io, ++ 0, ++ port_priv->ethsw_data->dpsw_handle, ++ port_priv->idx, ++ (u16)ETHSW_L2_MAX_FRM(mtu)); ++ if (err) { ++ netdev_err(netdev, ++ "dpsw_if_set_max_frame_length() err %d\n", err); ++ return err; + } + -+ nla_nest_end(skb, nest); -+ ++ netdev->mtu = mtu; + return 0; -+nla_put_err: -+ netdev_err(netdev, "nla_put_ err %d\n", err); -+ nla_nest_cancel(skb, nest); -+ return err; +} + -+static int ethsw_getlink(struct sk_buff *skb, u32 pid, u32 seq, -+ struct net_device *netdev, u32 filter_mask, -+ int nlflags) ++static int port_carrier_state_sync(struct net_device *netdev) +{ -+ struct ethsw_dev_priv *priv; -+ struct ethsw_port_priv *port_priv = NULL; -+ struct ifinfomsg *hdr; -+ struct nlmsghdr *nlh; ++ struct ethsw_port_priv *port_priv = netdev_priv(netdev); ++ struct dpsw_link_state state; + int err; + -+ __get_priv(netdev, &priv, &port_priv); -+ -+ nlh = nlmsg_put(skb, pid, seq, RTM_NEWLINK, sizeof(*hdr), NLM_F_MULTI); -+ if (!nlh) -+ return -EMSGSIZE; -+ -+ hdr = nlmsg_data(nlh); -+ memset(hdr, 0, sizeof(*hdr)); -+ hdr->ifi_family = AF_BRIDGE; -+ hdr->ifi_type = netdev->type; -+ hdr->ifi_index = netdev->ifindex; -+ hdr->ifi_flags = dev_get_flags(netdev); -+ -+ err = __nla_put_netdev(skb, netdev, priv); -+ if (err) -+ goto nla_put_err; -+ -+ if (port_priv) { -+ err = __nla_put_port(skb, netdev, port_priv); -+ if (err) -+ goto nla_put_err; -+ } -+ -+ /* Check if the VID information is requested */ -+ if (filter_mask & RTEXT_FILTER_BRVLAN) { -+ err = __nla_put_vlan(skb, netdev, priv, port_priv); -+ if (err) -+ goto nla_put_err; ++ err = dpsw_if_get_link_state(port_priv->ethsw_data->mc_io, 0, ++ port_priv->ethsw_data->dpsw_handle, ++ port_priv->idx, &state); ++ if (err) { ++ netdev_err(netdev, "dpsw_if_get_link_state() err %d\n", err); ++ return err; + } + -+ nlmsg_end(skb, nlh); -+ return skb->len; ++ WARN_ONCE(state.up > 1, "Garbage read into link_state"); + -+nla_put_err: -+ nlmsg_cancel(skb, nlh); -+ return -EMSGSIZE; ++ if (state.up != port_priv->link_state) { ++ if (state.up) ++ netif_carrier_on(netdev); ++ else ++ netif_carrier_off(netdev); ++ port_priv->link_state = state.up; ++ } ++ return 0; +} + -+static int ethsw_dellink_switch(struct ethsw_dev_priv *priv, u16 vid) ++static int port_open(struct net_device *netdev) +{ -+ struct list_head *pos; -+ struct ethsw_port_priv *ppriv_local = NULL; -+ int err = 0; ++ struct ethsw_port_priv *port_priv = netdev_priv(netdev); ++ int err; + -+ if (!priv->vlans[vid]) -+ return -ENOENT; ++ /* No need to allow Tx as control interface is disabled */ ++ netif_tx_stop_all_queues(netdev); + -+ err = dpsw_vlan_remove(priv->mc_io, 0, priv->dpsw_handle, vid); ++ err = dpsw_if_enable(port_priv->ethsw_data->mc_io, 0, ++ port_priv->ethsw_data->dpsw_handle, ++ port_priv->idx); + if (err) { -+ netdev_err(priv->netdev, "dpsw_vlan_remove err %d\n", err); ++ netdev_err(netdev, "dpsw_if_enable err %d\n", err); + return err; + } -+ priv->vlans[vid] = 0; + -+ list_for_each(pos, &priv->port_list) { -+ ppriv_local = list_entry(pos, struct ethsw_port_priv, -+ list); -+ ppriv_local->vlans[vid] = 0; ++ /* sync carrier state */ ++ err = port_carrier_state_sync(netdev); ++ if (err) { ++ netdev_err(netdev, ++ "port_carrier_state_sync err %d\n", err); ++ goto err_carrier_sync; + } + + return 0; ++ ++err_carrier_sync: ++ dpsw_if_disable(port_priv->ethsw_data->mc_io, 0, ++ port_priv->ethsw_data->dpsw_handle, ++ port_priv->idx); ++ return err; +} + -+static int ethsw_dellink_port(struct ethsw_dev_priv *priv, -+ struct ethsw_port_priv *port_priv, -+ u16 vid) ++static int port_stop(struct net_device *netdev) +{ -+ struct list_head *pos; -+ struct ethsw_port_priv *ppriv_local = NULL; -+ struct dpsw_vlan_if_cfg vcfg = { -+ .num_ifs = 1, -+ .if_id[0] = port_priv->port_index, -+ }; -+ unsigned int count = 0; -+ int err = 0; -+ -+ if (!port_priv->vlans[vid]) -+ return -ENOENT; -+ -+ /* VLAN will be deleted from switch if global flag is not set -+ * and is configured on only one port -+ */ -+ if (!(priv->vlans[vid] & ETHSW_VLAN_GLOBAL)) { -+ list_for_each(pos, &priv->port_list) { -+ ppriv_local = list_entry(pos, struct ethsw_port_priv, -+ list); -+ if (ppriv_local->vlans[vid] & ETHSW_VLAN_MEMBER) -+ count++; -+ } -+ -+ if (count == 1) -+ return ethsw_dellink_switch(priv, vid); -+ } ++ struct ethsw_port_priv *port_priv = netdev_priv(netdev); ++ int err; + -+ err = dpsw_vlan_remove_if(priv->mc_io, 0, priv->dpsw_handle, -+ vid, &vcfg); ++ err = dpsw_if_disable(port_priv->ethsw_data->mc_io, 0, ++ port_priv->ethsw_data->dpsw_handle, ++ port_priv->idx); + if (err) { -+ netdev_err(priv->netdev, "dpsw_vlan_remove_if err %d\n", err); ++ netdev_err(netdev, "dpsw_if_disable err %d\n", err); + return err; + } -+ port_priv->vlans[vid] = 0; ++ + return 0; +} + -+static int ethsw_dellink(struct net_device *netdev, -+ struct nlmsghdr *nlh, -+ u16 flags) ++static netdev_tx_t port_dropframe(struct sk_buff *skb, ++ struct net_device *netdev) +{ -+ struct nlattr *tb[IFLA_BRIDGE_MAX + 1]; -+ struct nlattr *spec; -+ struct bridge_vlan_info *vinfo; -+ struct ethsw_dev_priv *priv; -+ struct ethsw_port_priv *port_priv = NULL; -+ int err = 0; -+ -+ spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC); -+ if (!spec) -+ return 0; ++ /* we don't support I/O for now, drop the frame */ ++ dev_kfree_skb_any(skb); + -+ err = nla_parse_nested(tb, IFLA_BRIDGE_MAX, spec, ifla_br_policy); -+ if (err) -+ return err; ++ return NETDEV_TX_OK; ++} + -+ if (!tb[IFLA_BRIDGE_VLAN_INFO]) -+ return -EOPNOTSUPP; ++static const struct net_device_ops ethsw_port_ops = { ++ .ndo_open = port_open, ++ .ndo_stop = port_stop, + -+ vinfo = nla_data(tb[IFLA_BRIDGE_VLAN_INFO]); ++ .ndo_set_mac_address = eth_mac_addr, ++ .ndo_change_mtu = port_change_mtu, ++ .ndo_has_offload_stats = port_has_offload_stats, ++ .ndo_get_offload_stats = port_get_offload_stats, + -+ if (!vinfo->vid || vinfo->vid > VLAN_VID_MASK) -+ return -EINVAL; ++ .ndo_start_xmit = port_dropframe, ++}; + -+ __get_priv(netdev, &priv, &port_priv); ++static void ethsw_links_state_update(struct ethsw_core *ethsw) ++{ ++ int i; + -+ /* decide if command targets switch device or port */ -+ if (!port_priv) -+ err = ethsw_dellink_switch(priv, vinfo->vid); -+ else -+ err = ethsw_dellink_port(priv, port_priv, vinfo->vid); ++ for (i = 0; i < ethsw->sw_attr.num_ifs; i++) ++ port_carrier_state_sync(ethsw->ports[i]->netdev); ++} + -+ return err; ++static irqreturn_t ethsw_irq0_handler(int irq_num, void *arg) ++{ ++ return IRQ_WAKE_THREAD; +} + -+static const struct net_device_ops ethsw_ops = { -+ .ndo_open = ðsw_open, -+ .ndo_stop = ðsw_stop, ++static irqreturn_t ethsw_irq0_handler_thread(int irq_num, void *arg) ++{ ++ struct device *dev = (struct device *)arg; ++ struct ethsw_core *ethsw = dev_get_drvdata(dev); ++ ++ /* Mask the events and the if_id reserved bits to be cleared on read */ ++ u32 status = DPSW_IRQ_EVENT_LINK_CHANGED | 0xFFFF0000; ++ int err; + -+ .ndo_bridge_setlink = ðsw_setlink, -+ .ndo_bridge_getlink = ðsw_getlink, -+ .ndo_bridge_dellink = ðsw_dellink, ++ err = dpsw_get_irq_status(ethsw->mc_io, 0, ethsw->dpsw_handle, ++ DPSW_IRQ_INDEX_IF, &status); ++ if (err) { ++ dev_err(dev, "Can't get irq status (err %d)", err); + -+ .ndo_start_xmit = ðsw_dropframe, -+}; ++ err = dpsw_clear_irq_status(ethsw->mc_io, 0, ethsw->dpsw_handle, ++ DPSW_IRQ_INDEX_IF, 0xFFFFFFFF); ++ if (err) ++ dev_err(dev, "Can't clear irq status (err %d)", err); ++ goto out; ++ } + -+/*--------------------------------------------------------------------------- */ -+/* switch port netdevice ops */ ++ if (status & DPSW_IRQ_EVENT_LINK_CHANGED) ++ ethsw_links_state_update(ethsw); + -+static int _ethsw_port_carrier_state_sync(struct net_device *netdev) ++out: ++ return IRQ_HANDLED; ++} ++ ++static int ethsw_setup_irqs(struct fsl_mc_device *sw_dev) +{ -+ struct ethsw_port_priv *port_priv = netdev_priv(netdev); -+ struct dpsw_link_state state; -+ int err; ++ struct device *dev = &sw_dev->dev; ++ struct ethsw_core *ethsw = dev_get_drvdata(dev); ++ u32 mask = DPSW_IRQ_EVENT_LINK_CHANGED; ++ struct fsl_mc_device_irq *irq; ++ int err; + -+ err = dpsw_if_get_link_state(port_priv->ethsw_priv->mc_io, 0, -+ port_priv->ethsw_priv->dpsw_handle, -+ port_priv->port_index, &state); -+ if (unlikely(err)) { -+ netdev_err(netdev, "dpsw_if_get_link_state() err %d\n", err); ++ err = fsl_mc_allocate_irqs(sw_dev); ++ if (err) { ++ dev_err(dev, "MC irqs allocation failed\n"); + return err; + } + -+ WARN_ONCE(state.up > 1, "Garbage read into link_state"); ++ if (WARN_ON(sw_dev->obj_desc.irq_count != DPSW_IRQ_NUM)) { ++ err = -EINVAL; ++ goto free_irq; ++ } + -+ if (state.up) -+ netif_carrier_on(port_priv->netdev); -+ else -+ netif_carrier_off(port_priv->netdev); ++ err = dpsw_set_irq_enable(ethsw->mc_io, 0, ethsw->dpsw_handle, ++ DPSW_IRQ_INDEX_IF, 0); ++ if (err) { ++ dev_err(dev, "dpsw_set_irq_enable err %d\n", err); ++ goto free_irq; ++ } + -+ return 0; -+} ++ irq = sw_dev->irqs[DPSW_IRQ_INDEX_IF]; + -+static int ethsw_port_open(struct net_device *netdev) -+{ -+ struct ethsw_port_priv *port_priv = netdev_priv(netdev); -+ int err; ++ err = devm_request_threaded_irq(dev, irq->msi_desc->irq, ++ ethsw_irq0_handler, ++ ethsw_irq0_handler_thread, ++ IRQF_NO_SUSPEND | IRQF_ONESHOT, ++ dev_name(dev), dev); ++ if (err) { ++ dev_err(dev, "devm_request_threaded_irq(): %d", err); ++ goto free_irq; ++ } + -+ err = dpsw_if_enable(port_priv->ethsw_priv->mc_io, 0, -+ port_priv->ethsw_priv->dpsw_handle, -+ port_priv->port_index); ++ err = dpsw_set_irq_mask(ethsw->mc_io, 0, ethsw->dpsw_handle, ++ DPSW_IRQ_INDEX_IF, mask); + if (err) { -+ netdev_err(netdev, "dpsw_if_enable err %d\n", err); -+ return err; ++ dev_err(dev, "dpsw_set_irq_mask(): %d", err); ++ goto free_devm_irq; + } + -+ /* sync carrier state */ -+ err = _ethsw_port_carrier_state_sync(netdev); ++ err = dpsw_set_irq_enable(ethsw->mc_io, 0, ethsw->dpsw_handle, ++ DPSW_IRQ_INDEX_IF, 1); + if (err) { -+ netdev_err(netdev, "_ethsw_port_carrier_state_sync err %d\n", -+ err); -+ goto err_carrier_sync; ++ dev_err(dev, "dpsw_set_irq_enable(): %d", err); ++ goto free_devm_irq; + } + + return 0; + -+err_carrier_sync: -+ dpsw_if_disable(port_priv->ethsw_priv->mc_io, 0, -+ port_priv->ethsw_priv->dpsw_handle, -+ port_priv->port_index); ++free_devm_irq: ++ devm_free_irq(dev, irq->msi_desc->irq, dev); ++free_irq: ++ fsl_mc_free_irqs(sw_dev); + return err; +} + -+static int ethsw_port_stop(struct net_device *netdev) ++static void ethsw_teardown_irqs(struct fsl_mc_device *sw_dev) +{ -+ struct ethsw_port_priv *port_priv = netdev_priv(netdev); -+ int err; ++ struct device *dev = &sw_dev->dev; ++ struct ethsw_core *ethsw = dev_get_drvdata(dev); ++ struct fsl_mc_device_irq *irq; ++ int err; + -+ err = dpsw_if_disable(port_priv->ethsw_priv->mc_io, 0, -+ port_priv->ethsw_priv->dpsw_handle, -+ port_priv->port_index); -+ if (err) { -+ netdev_err(netdev, "dpsw_if_disable err %d\n", err); -+ return err; -+ } ++ irq = sw_dev->irqs[DPSW_IRQ_INDEX_IF]; ++ err = dpsw_set_irq_enable(ethsw->mc_io, 0, ethsw->dpsw_handle, ++ DPSW_IRQ_INDEX_IF, 0); ++ if (err) ++ dev_err(dev, "dpsw_set_irq_enable err %d\n", err); + -+ return 0; ++ fsl_mc_free_irqs(sw_dev); +} + -+static int ethsw_port_fdb_add_uc(struct net_device *netdev, -+ const unsigned char *addr) ++static int swdev_port_attr_get(struct net_device *netdev, ++ struct switchdev_attr *attr) +{ -+ struct ethsw_port_priv *port_priv = netdev_priv(netdev); -+ struct dpsw_fdb_unicast_cfg entry = {0}; -+ int err; ++ struct ethsw_port_priv *port_priv = netdev_priv(netdev); + -+ entry.if_egress = port_priv->port_index; -+ entry.type = DPSW_FDB_ENTRY_STATIC; -+ ether_addr_copy(entry.mac_addr, addr); ++ switch (attr->id) { ++ case SWITCHDEV_ATTR_ID_PORT_PARENT_ID: ++ attr->u.ppid.id_len = 1; ++ attr->u.ppid.id[0] = port_priv->ethsw_data->dev_id; ++ break; ++ case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: ++ attr->u.brport_flags = ++ (port_priv->ethsw_data->learning ? BR_LEARNING : 0) | ++ (port_priv->flood ? BR_FLOOD : 0); ++ break; ++ case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT: ++ attr->u.brport_flags_support = BR_LEARNING | BR_FLOOD; ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } + -+ err = dpsw_fdb_add_unicast(port_priv->ethsw_priv->mc_io, 0, -+ port_priv->ethsw_priv->dpsw_handle, -+ 0, &entry); -+ if (err) -+ netdev_err(netdev, "dpsw_fdb_add_unicast err %d\n", err); -+ return err; ++ return 0; +} + -+static int ethsw_port_fdb_del_uc(struct net_device *netdev, -+ const unsigned char *addr) ++static int port_attr_stp_state_set(struct net_device *netdev, ++ struct switchdev_trans *trans, ++ u8 state) +{ -+ struct ethsw_port_priv *port_priv = netdev_priv(netdev); -+ struct dpsw_fdb_unicast_cfg entry = {0}; -+ int err; ++ struct ethsw_port_priv *port_priv = netdev_priv(netdev); + -+ entry.if_egress = port_priv->port_index; -+ entry.type = DPSW_FDB_ENTRY_STATIC; -+ ether_addr_copy(entry.mac_addr, addr); ++ if (switchdev_trans_ph_prepare(trans)) ++ return 0; + -+ err = dpsw_fdb_remove_unicast(port_priv->ethsw_priv->mc_io, 0, -+ port_priv->ethsw_priv->dpsw_handle, -+ 0, &entry); -+ if (err) -+ netdev_err(netdev, "dpsw_fdb_remove_unicast err %d\n", err); -+ return err; ++ return ethsw_port_set_stp_state(port_priv, state); +} + -+static int ethsw_port_fdb_add_mc(struct net_device *netdev, -+ const unsigned char *addr) ++static int port_attr_br_flags_set(struct net_device *netdev, ++ struct switchdev_trans *trans, ++ unsigned long flags) +{ -+ struct ethsw_port_priv *port_priv = netdev_priv(netdev); -+ struct dpsw_fdb_multicast_cfg entry = {0}; -+ int err; ++ struct ethsw_port_priv *port_priv = netdev_priv(netdev); ++ int err = 0; + -+ ether_addr_copy(entry.mac_addr, addr); -+ entry.type = DPSW_FDB_ENTRY_STATIC; -+ entry.num_ifs = 1; -+ entry.if_id[0] = port_priv->port_index; ++ if (switchdev_trans_ph_prepare(trans)) ++ return 0; + -+ err = dpsw_fdb_add_multicast(port_priv->ethsw_priv->mc_io, 0, -+ port_priv->ethsw_priv->dpsw_handle, -+ 0, &entry); ++ /* Learning is enabled per switch */ ++ err = ethsw_set_learning(port_priv->ethsw_data, !!(flags & BR_LEARNING)); + if (err) -+ netdev_err(netdev, "dpsw_fdb_add_multicast err %d\n", err); ++ goto exit; ++ ++ err = ethsw_port_set_flood(port_priv, !!(flags & BR_FLOOD)); ++ ++exit: + return err; +} + -+static int ethsw_port_fdb_del_mc(struct net_device *netdev, -+ const unsigned char *addr) ++static int swdev_port_attr_set(struct net_device *netdev, ++ const struct switchdev_attr *attr, ++ struct switchdev_trans *trans) +{ -+ struct ethsw_port_priv *port_priv = netdev_priv(netdev); -+ struct dpsw_fdb_multicast_cfg entry = {0}; -+ int err; ++ int err = 0; + -+ ether_addr_copy(entry.mac_addr, addr); -+ entry.type = DPSW_FDB_ENTRY_STATIC; -+ entry.num_ifs = 1; -+ entry.if_id[0] = port_priv->port_index; ++ switch (attr->id) { ++ case SWITCHDEV_ATTR_ID_PORT_STP_STATE: ++ err = port_attr_stp_state_set(netdev, trans, ++ attr->u.stp_state); ++ break; ++ case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: ++ err = port_attr_br_flags_set(netdev, trans, ++ attr->u.brport_flags); ++ break; ++ case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING: ++ /* VLANs are supported by default */ ++ break; ++ default: ++ err = -EOPNOTSUPP; ++ break; ++ } + -+ err = dpsw_fdb_remove_multicast(port_priv->ethsw_priv->mc_io, 0, -+ port_priv->ethsw_priv->dpsw_handle, -+ 0, &entry); -+ if (err) -+ netdev_err(netdev, "dpsw_fdb_remove_multicast err %d\n", err); + return err; +} + -+static int _lookup_address(struct net_device *netdev, int is_uc, -+ const unsigned char *addr) ++static int port_vlans_add(struct net_device *netdev, ++ const struct switchdev_obj_port_vlan *vlan, ++ struct switchdev_trans *trans) +{ -+ struct netdev_hw_addr *ha; -+ struct netdev_hw_addr_list *list = (is_uc) ? &netdev->uc : &netdev->mc; ++ struct ethsw_port_priv *port_priv = netdev_priv(netdev); ++ int vid, err; + -+ netif_addr_lock_bh(netdev); -+ list_for_each_entry(ha, &list->list, list) { -+ if (ether_addr_equal(ha->addr, addr)) { -+ netif_addr_unlock_bh(netdev); -+ return 1; ++ if (switchdev_trans_ph_prepare(trans)) ++ return 0; ++ ++ for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { ++ if (!port_priv->ethsw_data->vlans[vid]) { ++ /* this is a new VLAN */ ++ err = ethsw_add_vlan(port_priv->ethsw_data, vid); ++ if (err) ++ return err; ++ ++ port_priv->ethsw_data->vlans[vid] |= ETHSW_VLAN_GLOBAL; + } ++ err = ethsw_port_add_vlan(port_priv, vid, vlan->flags); ++ if (err) ++ break; + } -+ netif_addr_unlock_bh(netdev); -+ return 0; ++ ++ return err; +} + -+static int ethsw_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], -+ struct net_device *netdev, -+ const unsigned char *addr, u16 vid, -+ u16 flags) ++static int swdev_port_obj_add(struct net_device *netdev, ++ const struct switchdev_obj *obj, ++ struct switchdev_trans *trans) +{ -+ struct list_head *pos; -+ struct ethsw_port_priv *port_priv = netdev_priv(netdev); -+ struct ethsw_dev_priv *priv = port_priv->ethsw_priv; + int err; + -+ /* TODO: add replace support when added to iproute bridge */ -+ if (!(flags & NLM_F_REQUEST)) { -+ netdev_err(netdev, -+ "ethsw_port_fdb_add unexpected flags value %08x\n", -+ flags); -+ return -EINVAL; ++ switch (obj->id) { ++ case SWITCHDEV_OBJ_ID_PORT_VLAN: ++ err = port_vlans_add(netdev, ++ SWITCHDEV_OBJ_PORT_VLAN(obj), ++ trans); ++ break; ++ default: ++ err = -EOPNOTSUPP; ++ break; + } + -+ if (is_unicast_ether_addr(addr)) { -+ /* if entry cannot be replaced, return error if exists */ -+ if (flags & NLM_F_EXCL || flags & NLM_F_APPEND) { -+ list_for_each(pos, &priv->port_list) { -+ port_priv = list_entry(pos, -+ struct ethsw_port_priv, -+ list); -+ if (_lookup_address(port_priv->netdev, -+ 1, addr)) -+ return -EEXIST; -+ } -+ } -+ -+ err = ethsw_port_fdb_add_uc(netdev, addr); -+ if (err) { -+ netdev_err(netdev, "ethsw_port_fdb_add_uc err %d\n", -+ err); -+ return err; -+ } -+ -+ /* we might have replaced an existing entry for a different -+ * switch port, make sure the address doesn't linger in any -+ * port address list -+ */ -+ list_for_each(pos, &priv->port_list) { -+ port_priv = list_entry(pos, struct ethsw_port_priv, -+ list); -+ dev_uc_del(port_priv->netdev, addr); -+ } ++ return err; ++} + -+ err = dev_uc_add(netdev, addr); -+ if (err) { -+ netdev_err(netdev, "dev_uc_add err %d\n", err); -+ return err; -+ } -+ } else { -+ struct dpsw_fdb_multicast_cfg entry = { -+ .type = DPSW_FDB_ENTRY_STATIC, -+ .num_ifs = 0, -+ }; ++static int ethsw_port_del_vlan(struct ethsw_port_priv *port_priv, u16 vid) ++{ ++ struct ethsw_core *ethsw = port_priv->ethsw_data; ++ struct net_device *netdev = port_priv->netdev; ++ struct dpsw_vlan_if_cfg vcfg; ++ int i, err; + -+ /* check if address is already set on this port */ -+ if (_lookup_address(netdev, 0, addr)) -+ return -EEXIST; ++ if (!port_priv->vlans[vid]) ++ return -ENOENT; + -+ /* check if the address exists on other port */ -+ ether_addr_copy(entry.mac_addr, addr); -+ err = dpsw_fdb_get_multicast(priv->mc_io, 0, priv->dpsw_handle, -+ 0, &entry); -+ if (!err) { -+ /* entry exists, can we replace it? */ -+ if (flags & NLM_F_EXCL) -+ return -EEXIST; -+ } else if (err != -ENAVAIL) { -+ netdev_err(netdev, "dpsw_fdb_get_unicast err %d\n", -+ err); ++ if (port_priv->vlans[vid] & ETHSW_VLAN_PVID) { ++ err = ethsw_port_set_pvid(port_priv, 0); ++ if (err) + return err; -+ } ++ } + -+ err = ethsw_port_fdb_add_mc(netdev, addr); ++ vcfg.num_ifs = 1; ++ vcfg.if_id[0] = port_priv->idx; ++ if (port_priv->vlans[vid] & ETHSW_VLAN_UNTAGGED) { ++ err = dpsw_vlan_remove_if_untagged(ethsw->mc_io, 0, ++ ethsw->dpsw_handle, ++ vid, &vcfg); + if (err) { -+ netdev_err(netdev, "ethsw_port_fdb_add_mc err %d\n", ++ netdev_err(netdev, ++ "dpsw_vlan_remove_if_untagged err %d\n", + err); -+ return err; -+ } -+ -+ err = dev_mc_add(netdev, addr); -+ if (err) { -+ netdev_err(netdev, "dev_mc_add err %d\n", err); -+ return err; + } ++ port_priv->vlans[vid] &= ~ETHSW_VLAN_UNTAGGED; + } + -+ return 0; -+} -+ -+static int ethsw_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], -+ struct net_device *netdev, -+ const unsigned char *addr, u16 vid) -+{ -+ int err; -+ -+ if (is_unicast_ether_addr(addr)) { -+ err = ethsw_port_fdb_del_uc(netdev, addr); ++ if (port_priv->vlans[vid] & ETHSW_VLAN_MEMBER) { ++ err = dpsw_vlan_remove_if(ethsw->mc_io, 0, ethsw->dpsw_handle, ++ vid, &vcfg); + if (err) { -+ netdev_err(netdev, "ethsw_port_fdb_del_uc err %d\n", -+ err); ++ netdev_err(netdev, ++ "dpsw_vlan_remove_if err %d\n", err); + return err; + } ++ port_priv->vlans[vid] &= ~ETHSW_VLAN_MEMBER; + -+ /* also delete if configured on port */ -+ err = dev_uc_del(netdev, addr); -+ if (err && err != -ENOENT) { -+ netdev_err(netdev, "dev_uc_del err %d\n", err); -+ return err; -+ } -+ } else { -+ if (!_lookup_address(netdev, 0, addr)) -+ return -ENOENT; ++ /* Delete VLAN from switch if it is no longer configured on ++ * any port ++ */ ++ for (i = 0; i < ethsw->sw_attr.num_ifs; i++) ++ if (ethsw->ports[i]->vlans[vid] & ETHSW_VLAN_MEMBER) ++ return 0; /* Found a port member in VID */ + -+ err = dev_mc_del(netdev, addr); -+ if (err) { -+ netdev_err(netdev, "dev_mc_del err %d\n", err); -+ return err; -+ } ++ ethsw->vlans[vid] &= ~ETHSW_VLAN_GLOBAL; + -+ err = ethsw_port_fdb_del_mc(netdev, addr); -+ if (err) { -+ netdev_err(netdev, "ethsw_port_fdb_del_mc err %d\n", -+ err); ++ err = ethsw_dellink_switch(ethsw, vid); ++ if (err) + return err; -+ } + } + + return 0; +} + -+struct rtnl_link_stats64 *ethsw_port_get_stats(struct net_device *netdev, -+ struct rtnl_link_stats64 *storage) ++static int port_vlans_del(struct net_device *netdev, ++ const struct switchdev_obj_port_vlan *vlan) +{ -+ struct ethsw_port_priv *port_priv = netdev_priv(netdev); -+ u64 tmp; -+ int err; -+ -+ err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0, -+ port_priv->ethsw_priv->dpsw_handle, -+ port_priv->port_index, -+ DPSW_CNT_ING_FRAME, &storage->rx_packets); -+ if (err) -+ goto error; -+ -+ err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0, -+ port_priv->ethsw_priv->dpsw_handle, -+ port_priv->port_index, -+ DPSW_CNT_EGR_FRAME, &storage->tx_packets); -+ if (err) -+ goto error; -+ -+ err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0, -+ port_priv->ethsw_priv->dpsw_handle, -+ port_priv->port_index, -+ DPSW_CNT_ING_BYTE, &storage->rx_bytes); -+ if (err) -+ goto error; -+ -+ err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0, -+ port_priv->ethsw_priv->dpsw_handle, -+ port_priv->port_index, -+ DPSW_CNT_EGR_BYTE, &storage->tx_bytes); -+ if (err) -+ goto error; -+ -+ err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0, -+ port_priv->ethsw_priv->dpsw_handle, -+ port_priv->port_index, -+ DPSW_CNT_ING_FRAME_DISCARD, -+ &storage->rx_dropped); -+ if (err) -+ goto error; -+ -+ err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0, -+ port_priv->ethsw_priv->dpsw_handle, -+ port_priv->port_index, -+ DPSW_CNT_ING_FLTR_FRAME, -+ &tmp); -+ if (err) -+ goto error; -+ storage->rx_dropped += tmp; -+ -+ err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0, -+ port_priv->ethsw_priv->dpsw_handle, -+ port_priv->port_index, -+ DPSW_CNT_EGR_FRAME_DISCARD, -+ &storage->tx_dropped); -+ if (err) -+ goto error; ++ struct ethsw_port_priv *port_priv = netdev_priv(netdev); ++ int vid, err; + -+ return storage; ++ for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { ++ err = ethsw_port_del_vlan(port_priv, vid); ++ if (err) ++ break; ++ } + -+error: -+ netdev_err(netdev, "dpsw_if_get_counter err %d\n", err); ++ return err; +} + -+static int ethsw_port_change_mtu(struct net_device *netdev, int mtu) ++static int swdev_port_obj_del(struct net_device *netdev, ++ const struct switchdev_obj *obj) +{ -+ struct ethsw_port_priv *port_priv = netdev_priv(netdev); -+ int err; -+ -+ if (mtu < ETH_ZLEN || mtu > ETHSW_MAX_FRAME_LENGTH) { -+ netdev_err(netdev, "Invalid MTU %d. Valid range is: %d..%d\n", -+ mtu, ETH_ZLEN, ETHSW_MAX_FRAME_LENGTH); -+ return -EINVAL; -+ } ++ int err; + -+ err = dpsw_if_set_max_frame_length(port_priv->ethsw_priv->mc_io, -+ 0, -+ port_priv->ethsw_priv->dpsw_handle, -+ port_priv->port_index, -+ (u16)ETHSW_L2_MAX_FRM(mtu)); -+ if (err) { -+ netdev_err(netdev, -+ "dpsw_if_set_max_frame_length() err %d\n", err); -+ return err; ++ switch (obj->id) { ++ case SWITCHDEV_OBJ_ID_PORT_VLAN: ++ err = port_vlans_del(netdev, SWITCHDEV_OBJ_PORT_VLAN(obj)); ++ break; ++ default: ++ err = -EOPNOTSUPP; ++ break; + } -+ -+ netdev->mtu = mtu; -+ return 0; ++ return err; +} + -+static const struct net_device_ops ethsw_port_ops = { -+ .ndo_open = ðsw_port_open, -+ .ndo_stop = ðsw_port_stop, -+ -+ .ndo_fdb_add = ðsw_port_fdb_add, -+ .ndo_fdb_del = ðsw_port_fdb_del, -+ .ndo_fdb_dump = &ndo_dflt_fdb_dump, -+ -+ .ndo_get_stats64 = ðsw_port_get_stats, -+ .ndo_change_mtu = ðsw_port_change_mtu, -+ -+ .ndo_start_xmit = ðsw_dropframe, ++static const struct switchdev_ops ethsw_port_switchdev_ops = { ++ .switchdev_port_attr_get = swdev_port_attr_get, ++ .switchdev_port_attr_set = swdev_port_attr_set, ++ .switchdev_port_obj_add = swdev_port_obj_add, ++ .switchdev_port_obj_del = swdev_port_obj_del, +}; + -+static void ethsw_get_drvinfo(struct net_device *netdev, -+ struct ethtool_drvinfo *drvinfo) ++/* For the moment, only flood setting needs to be updated */ ++static int port_bridge_join(struct net_device *netdev) +{ + struct ethsw_port_priv *port_priv = netdev_priv(netdev); -+ u16 version_major, version_minor; -+ int err; + -+ strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver)); -+ strlcpy(drvinfo->version, ethsw_drv_version, sizeof(drvinfo->version)); -+ -+ err = dpsw_get_api_version(port_priv->ethsw_priv->mc_io, 0, -+ &version_major, -+ &version_minor); -+ if (err) -+ strlcpy(drvinfo->fw_version, "N/A", -+ sizeof(drvinfo->fw_version)); -+ else -+ snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), -+ "%u.%u", version_major, version_minor); -+ -+ strlcpy(drvinfo->bus_info, dev_name(netdev->dev.parent->parent), -+ sizeof(drvinfo->bus_info)); ++ /* Enable flooding */ ++ return ethsw_port_set_flood(port_priv, 1); +} + -+static int ethsw_get_settings(struct net_device *netdev, -+ struct ethtool_cmd *cmd) ++static int port_bridge_leave(struct net_device *netdev) +{ + struct ethsw_port_priv *port_priv = netdev_priv(netdev); -+ struct dpsw_link_state state = {0}; -+ int err = 0; -+ -+ err = dpsw_if_get_link_state(port_priv->ethsw_priv->mc_io, 0, -+ port_priv->ethsw_priv->dpsw_handle, -+ port_priv->port_index, -+ &state); -+ if (err) { -+ netdev_err(netdev, "ERROR %d getting link state", err); -+ goto out; -+ } -+ -+ /* At the moment, we have no way of interrogating the DPMAC -+ * from the DPSW side or there may not exist a DPMAC at all. -+ * Report only autoneg state, duplexity and speed. -+ */ -+ if (state.options & DPSW_LINK_OPT_AUTONEG) -+ cmd->autoneg = AUTONEG_ENABLE; -+ if (!(state.options & DPSW_LINK_OPT_HALF_DUPLEX)) -+ cmd->autoneg = DUPLEX_FULL; -+ ethtool_cmd_speed_set(cmd, state.rate); + -+out: -+ return err; ++ /* Disable flooding */ ++ return ethsw_port_set_flood(port_priv, 0); +} + -+static int ethsw_set_settings(struct net_device *netdev, -+ struct ethtool_cmd *cmd) ++static int port_netdevice_event(struct notifier_block *unused, ++ unsigned long event, void *ptr) +{ -+ struct ethsw_port_priv *port_priv = netdev_priv(netdev); -+ struct dpsw_link_state state = {0}; -+ struct dpsw_link_cfg cfg = {0}; ++ struct net_device *netdev = netdev_notifier_info_to_dev(ptr); ++ struct netdev_notifier_changeupper_info *info = ptr; ++ struct net_device *upper_dev; + int err = 0; + -+ netdev_dbg(netdev, "Setting link parameters..."); -+ -+ err = dpsw_if_get_link_state(port_priv->ethsw_priv->mc_io, 0, -+ port_priv->ethsw_priv->dpsw_handle, -+ port_priv->port_index, -+ &state); -+ if (err) { -+ netdev_err(netdev, "ERROR %d getting link state", err); -+ goto out; -+ } -+ -+ /* Due to a temporary MC limitation, the DPSW port must be down -+ * in order to be able to change link settings. Taking steps to let -+ * the user know that. -+ */ -+ if (netif_running(netdev)) { -+ netdev_info(netdev, -+ "Sorry, interface must be brought down first.\n"); -+ return -EACCES; ++ if (netdev->netdev_ops != ðsw_port_ops) ++ return NOTIFY_DONE; ++ ++ /* Handle just upper dev link/unlink for the moment */ ++ if (event == NETDEV_CHANGEUPPER) { ++ upper_dev = info->upper_dev; ++ if (netif_is_bridge_master(upper_dev)) { ++ if (info->linking) ++ err = port_bridge_join(netdev); ++ else ++ err = port_bridge_leave(netdev); ++ } + } + -+ cfg.options = state.options; -+ cfg.rate = ethtool_cmd_speed(cmd); -+ if (cmd->autoneg == AUTONEG_ENABLE) -+ cfg.options |= DPSW_LINK_OPT_AUTONEG; -+ else -+ cfg.options &= ~DPSW_LINK_OPT_AUTONEG; -+ if (cmd->duplex == DUPLEX_HALF) -+ cfg.options |= DPSW_LINK_OPT_HALF_DUPLEX; -+ else -+ cfg.options &= ~DPSW_LINK_OPT_HALF_DUPLEX; -+ -+ err = dpsw_if_set_link_cfg(port_priv->ethsw_priv->mc_io, 0, -+ port_priv->ethsw_priv->dpsw_handle, -+ port_priv->port_index, -+ &cfg); -+ if (err) -+ /* ethtool will be loud enough if we return an error; no point -+ * in putting our own error message on the console by default -+ */ -+ netdev_dbg(netdev, "ERROR %d setting link cfg", err); -+ -+out: -+ return err; ++ return notifier_from_errno(err); +} + -+static struct { -+ enum dpsw_counter id; -+ char name[ETH_GSTRING_LEN]; -+} ethsw_ethtool_counters[] = { -+ {DPSW_CNT_ING_FRAME, "rx frames"}, -+ {DPSW_CNT_ING_BYTE, "rx bytes"}, -+ {DPSW_CNT_ING_FLTR_FRAME, "rx filtered frames"}, -+ {DPSW_CNT_ING_FRAME_DISCARD, "rx discarded frames"}, -+ {DPSW_CNT_ING_BCAST_FRAME, "rx b-cast frames"}, -+ {DPSW_CNT_ING_BCAST_BYTES, "rx b-cast bytes"}, -+ {DPSW_CNT_ING_MCAST_FRAME, "rx m-cast frames"}, -+ {DPSW_CNT_ING_MCAST_BYTE, "rx m-cast bytes"}, -+ {DPSW_CNT_EGR_FRAME, "tx frames"}, -+ {DPSW_CNT_EGR_BYTE, "tx bytes"}, -+ {DPSW_CNT_EGR_FRAME_DISCARD, "tx discarded frames"}, ++static struct notifier_block port_nb __read_mostly = { ++ .notifier_call = port_netdevice_event, ++}; + ++struct ethsw_switchdev_event_work { ++ struct work_struct work; ++ struct switchdev_notifier_fdb_info fdb_info; ++ struct net_device *dev; ++ unsigned long event; +}; + -+static int ethsw_ethtool_get_sset_count(struct net_device *dev, int sset) ++static void ethsw_switchdev_event_work(struct work_struct *work) +{ -+ switch (sset) { -+ case ETH_SS_STATS: -+ return ARRAY_SIZE(ethsw_ethtool_counters); -+ default: -+ return -EOPNOTSUPP; -+ } -+} ++ struct ethsw_switchdev_event_work *switchdev_work = ++ container_of(work, struct ethsw_switchdev_event_work, work); ++ struct net_device *dev = switchdev_work->dev; ++ struct switchdev_notifier_fdb_info *fdb_info; ++ struct ethsw_port_priv *port_priv; + -+static void ethsw_ethtool_get_strings(struct net_device *netdev, -+ u32 stringset, u8 *data) -+{ -+ u32 i; ++ rtnl_lock(); ++ port_priv = netdev_priv(dev); ++ fdb_info = &switchdev_work->fdb_info; + -+ switch (stringset) { -+ case ETH_SS_STATS: -+ for (i = 0; i < ARRAY_SIZE(ethsw_ethtool_counters); i++) -+ memcpy(data + i * ETH_GSTRING_LEN, -+ ethsw_ethtool_counters[i].name, ETH_GSTRING_LEN); ++ switch (switchdev_work->event) { ++ case SWITCHDEV_FDB_ADD_TO_DEVICE: ++ if (is_unicast_ether_addr(fdb_info->addr)) ++ ethsw_port_fdb_add_uc(netdev_priv(dev), fdb_info->addr); ++ else ++ ethsw_port_fdb_add_mc(netdev_priv(dev), fdb_info->addr); ++ break; ++ case SWITCHDEV_FDB_DEL_TO_DEVICE: ++ if (is_unicast_ether_addr(fdb_info->addr)) ++ ethsw_port_fdb_del_uc(netdev_priv(dev), fdb_info->addr); ++ else ++ ethsw_port_fdb_del_mc(netdev_priv(dev), fdb_info->addr); + break; + } ++ ++ rtnl_unlock(); ++ kfree(switchdev_work->fdb_info.addr); ++ kfree(switchdev_work); ++ dev_put(dev); +} + -+static void ethsw_ethtool_get_stats(struct net_device *netdev, -+ struct ethtool_stats *stats, -+ u64 *data) ++/* Called under rcu_read_lock() */ ++static int port_switchdev_event(struct notifier_block *unused, ++ unsigned long event, void *ptr) +{ -+ struct ethsw_port_priv *port_priv = netdev_priv(netdev); -+ u32 i; -+ int err; ++ struct net_device *dev = switchdev_notifier_info_to_dev(ptr); ++ struct ethsw_switchdev_event_work *switchdev_work; ++ struct switchdev_notifier_fdb_info *fdb_info = ptr; + -+ for (i = 0; i < ARRAY_SIZE(ethsw_ethtool_counters); i++) { -+ err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0, -+ port_priv->ethsw_priv->dpsw_handle, -+ port_priv->port_index, -+ ethsw_ethtool_counters[i].id, -+ &data[i]); -+ if (err) -+ netdev_err(netdev, "dpsw_if_get_counter[%s] err %d\n", -+ ethsw_ethtool_counters[i].name, err); -+ } -+} -+ -+static const struct ethtool_ops ethsw_port_ethtool_ops = { -+ .get_drvinfo = ðsw_get_drvinfo, -+ .get_link = ðtool_op_get_link, -+ .get_settings = ðsw_get_settings, -+ .set_settings = ðsw_set_settings, -+ .get_strings = ðsw_ethtool_get_strings, -+ .get_ethtool_stats = ðsw_ethtool_get_stats, -+ .get_sset_count = ðsw_ethtool_get_sset_count, -+}; ++ switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC); ++ if (!switchdev_work) ++ return NOTIFY_BAD; + -+/* -------------------------------------------------------------------------- */ -+/* ethsw driver functions */ ++ INIT_WORK(&switchdev_work->work, ethsw_switchdev_event_work); ++ switchdev_work->dev = dev; ++ switchdev_work->event = event; + -+static int ethsw_links_state_update(struct ethsw_dev_priv *priv) -+{ -+ struct list_head *pos; -+ struct ethsw_port_priv *port_priv; -+ int err; ++ switch (event) { ++ case SWITCHDEV_FDB_ADD_TO_DEVICE: ++ case SWITCHDEV_FDB_DEL_TO_DEVICE: ++ memcpy(&switchdev_work->fdb_info, ptr, ++ sizeof(switchdev_work->fdb_info)); ++ switchdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC); ++ if (!switchdev_work->fdb_info.addr) ++ goto err_addr_alloc; + -+ list_for_each(pos, &priv->port_list) { -+ port_priv = list_entry(pos, struct ethsw_port_priv, -+ list); ++ ether_addr_copy((u8 *)switchdev_work->fdb_info.addr, ++ fdb_info->addr); + -+ err = _ethsw_port_carrier_state_sync(port_priv->netdev); -+ if (err) -+ netdev_err(port_priv->netdev, -+ "_ethsw_port_carrier_state_sync err %d\n", -+ err); ++ /* Take a reference on the device to avoid being freed. */ ++ dev_hold(dev); ++ break; ++ default: ++ return NOTIFY_DONE; + } + -+ return 0; -+} ++ queue_work(ethsw_owq, &switchdev_work->work); + -+static irqreturn_t ethsw_irq0_handler(int irq_num, void *arg) -+{ -+ return IRQ_WAKE_THREAD; -+} ++ return NOTIFY_DONE; + -+static irqreturn_t _ethsw_irq0_handler_thread(int irq_num, void *arg) -+{ -+ struct device *dev = (struct device *)arg; -+ struct net_device *netdev = dev_get_drvdata(dev); -+ struct ethsw_dev_priv *priv = netdev_priv(netdev); ++err_addr_alloc: ++ kfree(switchdev_work); ++ return NOTIFY_BAD; ++} + -+ struct fsl_mc_io *io = priv->mc_io; -+ u16 token = priv->dpsw_handle; -+ int irq_index = DPSW_IRQ_INDEX_IF; ++static struct notifier_block port_switchdev_nb = { ++ .notifier_call = port_switchdev_event, ++}; + -+ /* Mask the events and the if_id reserved bits to be cleared on read */ -+ u32 status = DPSW_IRQ_EVENT_LINK_CHANGED | 0xFFFF0000; ++static int ethsw_register_notifier(struct device *dev) ++{ + int err; + -+ err = dpsw_get_irq_status(io, 0, token, irq_index, &status); -+ if (unlikely(err)) { -+ netdev_err(netdev, "Can't get irq status (err %d)", err); -+ -+ err = dpsw_clear_irq_status(io, 0, token, irq_index, -+ 0xFFFFFFFF); -+ if (unlikely(err)) -+ netdev_err(netdev, "Can't clear irq status (err %d)", -+ err); -+ goto out; ++ err = register_netdevice_notifier(&port_nb); ++ if (err) { ++ dev_err(dev, "Failed to register netdev notifier\n"); ++ return err; + } + -+ if (status & DPSW_IRQ_EVENT_LINK_CHANGED) { -+ err = ethsw_links_state_update(priv); -+ if (unlikely(err)) -+ goto out; ++ err = register_switchdev_notifier(&port_switchdev_nb); ++ if (err) { ++ dev_err(dev, "Failed to register switchdev notifier\n"); ++ goto err_switchdev_nb; + } + -+out: -+ return IRQ_HANDLED; ++ return 0; ++ ++err_switchdev_nb: ++ unregister_netdevice_notifier(&port_nb); ++ return err; +} + -+static int ethsw_setup_irqs(struct fsl_mc_device *sw_dev) ++static int ethsw_open(struct ethsw_core *ethsw) +{ -+ struct device *dev = &sw_dev->dev; -+ struct net_device *netdev = dev_get_drvdata(dev); -+ struct ethsw_dev_priv *priv = netdev_priv(netdev); -+ int err = 0; -+ struct fsl_mc_device_irq *irq; -+ const int irq_index = DPSW_IRQ_INDEX_IF; -+ u32 mask = DPSW_IRQ_EVENT_LINK_CHANGED; ++ struct ethsw_port_priv *port_priv = NULL; ++ int i, err; + -+ err = fsl_mc_allocate_irqs(sw_dev); -+ if (unlikely(err)) { -+ dev_err(dev, "MC irqs allocation failed\n"); ++ err = dpsw_enable(ethsw->mc_io, 0, ethsw->dpsw_handle); ++ if (err) { ++ dev_err(ethsw->dev, "dpsw_enable err %d\n", err); + return err; + } + -+ if (WARN_ON(sw_dev->obj_desc.irq_count != DPSW_MAX_IRQ_NUM)) { -+ err = -EINVAL; -+ goto free_irq; -+ } -+ -+ err = dpsw_set_irq_enable(priv->mc_io, 0, priv->dpsw_handle, -+ irq_index, 0); -+ if (unlikely(err)) { -+ dev_err(dev, "dpsw_set_irq_enable err %d\n", err); -+ goto free_irq; ++ for (i = 0; i < ethsw->sw_attr.num_ifs; i++) { ++ port_priv = ethsw->ports[i]; ++ err = dev_open(port_priv->netdev); ++ if (err) { ++ netdev_err(port_priv->netdev, "dev_open err %d\n", err); ++ return err; ++ } + } + -+ irq = sw_dev->irqs[irq_index]; ++ return 0; ++} + -+ err = devm_request_threaded_irq(dev, irq->msi_desc->irq, -+ ethsw_irq0_handler, -+ _ethsw_irq0_handler_thread, -+ IRQF_NO_SUSPEND | IRQF_ONESHOT, -+ dev_name(dev), dev); -+ if (unlikely(err)) { -+ dev_err(dev, "devm_request_threaded_irq(): %d", err); -+ goto free_irq; -+ } ++static int ethsw_stop(struct ethsw_core *ethsw) ++{ ++ struct ethsw_port_priv *port_priv = NULL; ++ int i, err; + -+ err = dpsw_set_irq_mask(priv->mc_io, 0, priv->dpsw_handle, -+ irq_index, mask); -+ if (unlikely(err)) { -+ dev_err(dev, "dpsw_set_irq_mask(): %d", err); -+ goto free_devm_irq; ++ for (i = 0; i < ethsw->sw_attr.num_ifs; i++) { ++ port_priv = ethsw->ports[i]; ++ dev_close(port_priv->netdev); + } + -+ err = dpsw_set_irq_enable(priv->mc_io, 0, priv->dpsw_handle, -+ irq_index, 1); -+ if (unlikely(err)) { -+ dev_err(dev, "dpsw_set_irq_enable(): %d", err); -+ goto free_devm_irq; ++ err = dpsw_disable(ethsw->mc_io, 0, ethsw->dpsw_handle); ++ if (err) { ++ dev_err(ethsw->dev, "dpsw_disable err %d\n", err); ++ return err; + } + + return 0; -+ -+free_devm_irq: -+ devm_free_irq(dev, irq->msi_desc->irq, dev); -+free_irq: -+ fsl_mc_free_irqs(sw_dev); -+ return err; -+} -+ -+static void ethsw_teardown_irqs(struct fsl_mc_device *sw_dev) -+{ -+ struct device *dev = &sw_dev->dev; -+ struct net_device *netdev = dev_get_drvdata(dev); -+ struct ethsw_dev_priv *priv = netdev_priv(netdev); -+ -+ dpsw_set_irq_enable(priv->mc_io, 0, priv->dpsw_handle, -+ DPSW_IRQ_INDEX_IF, 0); -+ devm_free_irq(dev, -+ sw_dev->irqs[DPSW_IRQ_INDEX_IF]->msi_desc->irq, -+ dev); -+ fsl_mc_free_irqs(sw_dev); +} + -+static int __cold -+ethsw_init(struct fsl_mc_device *sw_dev) ++static int ethsw_init(struct fsl_mc_device *sw_dev) +{ -+ struct device *dev = &sw_dev->dev; -+ struct ethsw_dev_priv *priv; -+ struct net_device *netdev; -+ int err = 0; -+ u16 i; -+ u16 version_major, version_minor; -+ const struct dpsw_stp_cfg stp_cfg = { -+ .vlan_id = 1, -+ .state = DPSW_STP_STATE_FORWARDING, -+ }; -+ -+ netdev = dev_get_drvdata(dev); -+ priv = netdev_priv(netdev); ++ struct device *dev = &sw_dev->dev; ++ struct ethsw_core *ethsw = dev_get_drvdata(dev); ++ u16 version_major, version_minor, i; ++ struct dpsw_stp_cfg stp_cfg; ++ int err; + -+ priv->dev_id = sw_dev->obj_desc.id; ++ ethsw->dev_id = sw_dev->obj_desc.id; + -+ err = dpsw_open(priv->mc_io, 0, priv->dev_id, &priv->dpsw_handle); ++ err = dpsw_open(ethsw->mc_io, 0, ethsw->dev_id, ðsw->dpsw_handle); + if (err) { + dev_err(dev, "dpsw_open err %d\n", err); -+ goto err_exit; -+ } -+ if (!priv->dpsw_handle) { -+ dev_err(dev, "dpsw_open returned null handle but no error\n"); -+ err = -EFAULT; -+ goto err_exit; ++ return err; + } + -+ err = dpsw_get_attributes(priv->mc_io, 0, priv->dpsw_handle, -+ &priv->sw_attr); ++ err = dpsw_get_attributes(ethsw->mc_io, 0, ethsw->dpsw_handle, ++ ðsw->sw_attr); + if (err) { + dev_err(dev, "dpsw_get_attributes err %d\n", err); + goto err_close; + } + -+ err = dpsw_get_api_version(priv->mc_io, 0, ++ err = dpsw_get_api_version(ethsw->mc_io, 0, + &version_major, + &version_minor); + if (err) { @@ -16868,21 +16182,24 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + goto err_close; + } + -+ err = dpsw_reset(priv->mc_io, 0, priv->dpsw_handle); ++ err = dpsw_reset(ethsw->mc_io, 0, ethsw->dpsw_handle); + if (err) { + dev_err(dev, "dpsw_reset err %d\n", err); + goto err_close; + } + -+ err = dpsw_fdb_set_learning_mode(priv->mc_io, 0, priv->dpsw_handle, 0, ++ err = dpsw_fdb_set_learning_mode(ethsw->mc_io, 0, ethsw->dpsw_handle, 0, + DPSW_FDB_LEARNING_MODE_HW); + if (err) { + dev_err(dev, "dpsw_fdb_set_learning_mode err %d\n", err); + goto err_close; + } + -+ for (i = 0; i < priv->sw_attr.num_ifs; i++) { -+ err = dpsw_if_set_stp(priv->mc_io, 0, priv->dpsw_handle, i, ++ stp_cfg.vlan_id = DEFAULT_VLAN_ID; ++ stp_cfg.state = DPSW_STP_STATE_FORWARDING; ++ ++ for (i = 0; i < ethsw->sw_attr.num_ifs; i++) { ++ err = dpsw_if_set_stp(ethsw->mc_io, 0, ethsw->dpsw_handle, i, + &stp_cfg); + if (err) { + dev_err(dev, "dpsw_if_set_stp err %d for port %d\n", @@ -16890,8 +16207,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + goto err_close; + } + -+ err = dpsw_if_set_broadcast(priv->mc_io, 0, -+ priv->dpsw_handle, i, 1); ++ err = dpsw_if_set_broadcast(ethsw->mc_io, 0, ++ ethsw->dpsw_handle, i, 1); + if (err) { + dev_err(dev, + "dpsw_if_set_broadcast err %d for port %d\n", @@ -16900,225 +16217,253 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + } + } + ++ ethsw_owq = alloc_ordered_workqueue("%s_ordered", WQ_MEM_RECLAIM, ++ "ethsw"); ++ if (!ethsw_owq) { ++ err = -ENOMEM; ++ goto err_close; ++ } ++ ++ err = ethsw_register_notifier(dev); ++ if (err) ++ goto err_destroy_ordered_workqueue; ++ + return 0; + ++err_destroy_ordered_workqueue: ++ destroy_workqueue(ethsw_owq); ++ +err_close: -+ dpsw_close(priv->mc_io, 0, priv->dpsw_handle); -+err_exit: ++ dpsw_close(ethsw->mc_io, 0, ethsw->dpsw_handle); + return err; +} + -+static int __cold -+ethsw_takedown(struct fsl_mc_device *sw_dev) ++static int ethsw_port_init(struct ethsw_port_priv *port_priv, u16 port) +{ -+ struct device *dev = &sw_dev->dev; -+ struct net_device *netdev; -+ struct ethsw_dev_priv *priv; -+ int err; ++ const char def_mcast[ETH_ALEN] = {0x01, 0x00, 0x5e, 0x00, 0x00, 0x01}; ++ struct net_device *netdev = port_priv->netdev; ++ struct ethsw_core *ethsw = port_priv->ethsw_data; ++ struct dpsw_vlan_if_cfg vcfg; ++ int err; + -+ netdev = dev_get_drvdata(dev); -+ priv = netdev_priv(netdev); ++ /* Switch starts with all ports configured to VLAN 1. Need to ++ * remove this setting to allow configuration at bridge join ++ */ ++ vcfg.num_ifs = 1; ++ vcfg.if_id[0] = port_priv->idx; ++ ++ err = dpsw_vlan_remove_if_untagged(ethsw->mc_io, 0, ethsw->dpsw_handle, ++ DEFAULT_VLAN_ID, &vcfg); ++ if (err) { ++ netdev_err(netdev, "dpsw_vlan_remove_if_untagged err %d\n", ++ err); ++ return err; ++ } + -+ err = dpsw_close(priv->mc_io, 0, priv->dpsw_handle); ++ err = ethsw_port_set_pvid(port_priv, 0); + if (err) -+ dev_warn(dev, "dpsw_close err %d\n", err); ++ return err; + -+ return 0; ++ err = dpsw_vlan_remove_if(ethsw->mc_io, 0, ethsw->dpsw_handle, ++ DEFAULT_VLAN_ID, &vcfg); ++ if (err) { ++ netdev_err(netdev, "dpsw_vlan_remove_if err %d\n", err); ++ return err; ++ } ++ ++ err = ethsw_port_fdb_add_mc(port_priv, def_mcast); ++ ++ return err; +} + -+static int __cold -+ethsw_remove(struct fsl_mc_device *sw_dev) ++static void ethsw_unregister_notifier(struct device *dev) +{ -+ struct device *dev; -+ struct net_device *netdev; -+ struct ethsw_dev_priv *priv; -+ struct ethsw_port_priv *port_priv; -+ struct list_head *pos; ++ int err; ++ ++ err = unregister_switchdev_notifier(&port_switchdev_nb); ++ if (err) ++ dev_err(dev, ++ "Failed to unregister switchdev notifier (%d)\n", err); ++ ++ err = unregister_netdevice_notifier(&port_nb); ++ if (err) ++ dev_err(dev, ++ "Failed to unregister netdev notifier (%d)\n", err); ++} ++ ++static void ethsw_takedown(struct fsl_mc_device *sw_dev) ++{ ++ struct device *dev = &sw_dev->dev; ++ struct ethsw_core *ethsw = dev_get_drvdata(dev); ++ int err; ++ ++ ethsw_unregister_notifier(dev); ++ ++ err = dpsw_close(ethsw->mc_io, 0, ethsw->dpsw_handle); ++ if (err) ++ dev_warn(dev, "dpsw_close err %d\n", err); ++} ++ ++static int ethsw_remove(struct fsl_mc_device *sw_dev) ++{ ++ struct ethsw_port_priv *port_priv; ++ struct ethsw_core *ethsw; ++ struct device *dev; ++ int i; + + dev = &sw_dev->dev; -+ netdev = dev_get_drvdata(dev); -+ priv = netdev_priv(netdev); ++ ethsw = dev_get_drvdata(dev); + -+ list_for_each(pos, &priv->port_list) { -+ port_priv = list_entry(pos, struct ethsw_port_priv, list); ++ ethsw_teardown_irqs(sw_dev); + -+ rtnl_lock(); -+ netdev_upper_dev_unlink(port_priv->netdev, netdev); -+ rtnl_unlock(); ++ destroy_workqueue(ethsw_owq); + ++ rtnl_lock(); ++ ethsw_stop(ethsw); ++ rtnl_unlock(); ++ ++ for (i = 0; i < ethsw->sw_attr.num_ifs; i++) { ++ port_priv = ethsw->ports[i]; + unregister_netdev(port_priv->netdev); + free_netdev(port_priv->netdev); + } -+ -+ ethsw_teardown_irqs(sw_dev); -+ -+ unregister_netdev(netdev); ++ kfree(ethsw->ports); + + ethsw_takedown(sw_dev); -+ fsl_mc_portal_free(priv->mc_io); ++ fsl_mc_portal_free(ethsw->mc_io); ++ ++ kfree(ethsw); + + dev_set_drvdata(dev, NULL); -+ free_netdev(netdev); + + return 0; +} + -+static int __cold -+ethsw_probe(struct fsl_mc_device *sw_dev) ++static int ethsw_probe_port(struct ethsw_core *ethsw, u16 port_idx) +{ -+ struct device *dev; -+ struct net_device *netdev = NULL; -+ struct ethsw_dev_priv *priv = NULL; -+ int err = 0; -+ u16 i; -+ const char def_mcast[ETH_ALEN] = { -+ 0x01, 0x00, 0x5e, 0x00, 0x00, 0x01, -+ }; -+ char port_name[IFNAMSIZ]; -+ -+ dev = &sw_dev->dev; ++ struct ethsw_port_priv *port_priv; ++ struct device *dev = ethsw->dev; ++ struct net_device *port_netdev; ++ int err; + -+ /* register switch device, it's for management only - no I/O */ -+ netdev = alloc_etherdev(sizeof(*priv)); -+ if (!netdev) { ++ port_netdev = alloc_etherdev(sizeof(struct ethsw_port_priv)); ++ if (!port_netdev) { + dev_err(dev, "alloc_etherdev error\n"); + return -ENOMEM; + } -+ netdev->netdev_ops = ðsw_ops; + -+ SET_NETDEV_DEV(netdev, dev); -+ dev_set_drvdata(dev, netdev); ++ port_priv = netdev_priv(port_netdev); ++ port_priv->netdev = port_netdev; ++ port_priv->ethsw_data = ethsw; + -+ priv = netdev_priv(netdev); -+ priv->netdev = netdev; ++ port_priv->idx = port_idx; ++ port_priv->stp_state = BR_STATE_FORWARDING; + -+ err = fsl_mc_portal_allocate(sw_dev, 0, &priv->mc_io); -+ if (err) { -+ dev_err(dev, "fsl_mc_portal_allocate err %d\n", err); -+ goto err_free_netdev; -+ } -+ if (!priv->mc_io) { -+ dev_err(dev, "fsl_mc_portal_allocate returned null handle but no error\n"); -+ err = -EFAULT; -+ goto err_free_netdev; -+ } ++ /* Flooding is implicitly enabled */ ++ port_priv->flood = true; + -+ err = ethsw_init(sw_dev); -+ if (err) { -+ dev_err(dev, "switch init err %d\n", err); -+ goto err_free_cmdport; -+ } ++ SET_NETDEV_DEV(port_netdev, dev); ++ port_netdev->netdev_ops = ðsw_port_ops; ++ port_netdev->ethtool_ops = ðsw_port_ethtool_ops; ++ port_netdev->switchdev_ops = ðsw_port_switchdev_ops; + -+ netdev->flags = netdev->flags | IFF_PROMISC | IFF_MASTER; ++ /* Set MTU limits */ ++ port_netdev->min_mtu = ETH_MIN_MTU; ++ port_netdev->max_mtu = ETHSW_MAX_FRAME_LENGTH; + -+ /* TODO: should we hold rtnl_lock here? We can't register_netdev under -+ * lock -+ */ -+ dev_alloc_name(netdev, "sw%d"); -+ err = register_netdev(netdev); ++ err = register_netdev(port_netdev); + if (err < 0) { + dev_err(dev, "register_netdev error %d\n", err); -+ goto err_takedown; -+ } -+ if (err) -+ dev_info(dev, "register_netdev res %d\n", err); -+ -+ /* VLAN 1 is implicitly configured on the switch */ -+ priv->vlans[1] = ETHSW_VLAN_MEMBER; -+ /* Flooding, learning are implicitly enabled */ -+ priv->learning = true; -+ priv->flood = true; -+ -+ /* register switch ports */ -+ snprintf(port_name, IFNAMSIZ, "%sp%%d", netdev->name); -+ -+ INIT_LIST_HEAD(&priv->port_list); -+ for (i = 0; i < priv->sw_attr.num_ifs; i++) { -+ struct net_device *port_netdev; -+ struct ethsw_port_priv *port_priv; -+ -+ port_netdev = alloc_etherdev(sizeof(struct ethsw_port_priv)); -+ if (!port_netdev) { -+ dev_err(dev, "alloc_etherdev error\n"); -+ goto err_takedown; ++ free_netdev(port_netdev); ++ return err; + } + -+ port_priv = netdev_priv(port_netdev); -+ port_priv->netdev = port_netdev; -+ port_priv->ethsw_priv = priv; ++ ethsw->ports[port_idx] = port_priv; + -+ port_priv->port_index = i; -+ port_priv->stp_state = BR_STATE_FORWARDING; -+ /* VLAN 1 is configured by default on all switch ports */ -+ port_priv->vlans[1] = ETHSW_VLAN_MEMBER | ETHSW_VLAN_UNTAGGED | -+ ETHSW_VLAN_PVID; ++ return ethsw_port_init(port_priv, port_idx); ++} + -+ SET_NETDEV_DEV(port_netdev, dev); -+ port_netdev->netdev_ops = ðsw_port_ops; -+ port_netdev->ethtool_ops = ðsw_port_ethtool_ops; ++static int ethsw_probe(struct fsl_mc_device *sw_dev) ++{ ++ struct device *dev = &sw_dev->dev; ++ struct ethsw_core *ethsw; ++ int i, err; + -+ port_netdev->flags = port_netdev->flags | -+ IFF_PROMISC | IFF_SLAVE; ++ /* Allocate switch core*/ ++ ethsw = kzalloc(sizeof(*ethsw), GFP_KERNEL); + -+ dev_alloc_name(port_netdev, port_name); -+ err = register_netdev(port_netdev); -+ if (err < 0) { -+ dev_err(dev, "register_netdev error %d\n", err); -+ free_netdev(port_netdev); -+ goto err_takedown; -+ } ++ if (!ethsw) ++ return -ENOMEM; + -+ rtnl_lock(); ++ ethsw->dev = dev; ++ dev_set_drvdata(dev, ethsw); + -+ err = netdev_master_upper_dev_link(port_netdev, netdev, -+ NULL, NULL); -+ if (err) { -+ dev_err(dev, "netdev_master_upper_dev_link error %d\n", -+ err); -+ unregister_netdev(port_netdev); -+ free_netdev(port_netdev); -+ rtnl_unlock(); -+ goto err_takedown; -+ } ++ err = fsl_mc_portal_allocate(sw_dev, 0, ðsw->mc_io); ++ if (err) { ++ dev_err(dev, "fsl_mc_portal_allocate err %d\n", err); ++ goto err_free_drvdata; ++ } + -+ rtmsg_ifinfo(RTM_NEWLINK, port_netdev, IFF_SLAVE, GFP_KERNEL); ++ err = ethsw_init(sw_dev); ++ if (err) ++ goto err_free_cmdport; + -+ rtnl_unlock(); ++ /* DEFAULT_VLAN_ID is implicitly configured on the switch */ ++ ethsw->vlans[DEFAULT_VLAN_ID] = ETHSW_VLAN_MEMBER; + -+ list_add(&port_priv->list, &priv->port_list); ++ /* Learning is implicitly enabled */ ++ ethsw->learning = true; + -+ /* TODO: implmenet set_rm_mode instead of this */ -+ err = ethsw_port_fdb_add_mc(port_netdev, def_mcast); ++ ethsw->ports = kcalloc(ethsw->sw_attr.num_ifs, sizeof(*ethsw->ports), ++ GFP_KERNEL); ++ if (!(ethsw->ports)) { ++ err = -ENOMEM; ++ goto err_takedown; ++ } ++ ++ for (i = 0; i < ethsw->sw_attr.num_ifs; i++) { ++ err = ethsw_probe_port(ethsw, i); + if (err) -+ dev_warn(&netdev->dev, -+ "ethsw_port_fdb_add_mc err %d\n", err); ++ goto err_free_ports; + } + -+ /* the switch starts up enabled */ ++ /* Switch starts up enabled */ + rtnl_lock(); -+ err = dev_open(netdev); ++ err = ethsw_open(ethsw); + rtnl_unlock(); + if (err) -+ dev_warn(dev, "dev_open err %d\n", err); ++ goto err_free_ports; + -+ /* setup irqs */ ++ /* Setup IRQs */ + err = ethsw_setup_irqs(sw_dev); -+ if (unlikely(err)) { -+ dev_warn(dev, "ethsw_setup_irqs err %d\n", err); -+ goto err_takedown; -+ } ++ if (err) ++ goto err_stop; + -+ dev_info(&netdev->dev, -+ "probed %d port switch\n", priv->sw_attr.num_ifs); ++ dev_info(dev, "probed %d port switch\n", ethsw->sw_attr.num_ifs); + return 0; + ++err_stop: ++ rtnl_lock(); ++ ethsw_stop(ethsw); ++ rtnl_unlock(); ++ ++err_free_ports: ++ /* Cleanup registered ports only */ ++ for (i--; i >= 0; i--) { ++ unregister_netdev(ethsw->ports[i]->netdev); ++ free_netdev(ethsw->ports[i]->netdev); ++ } ++ kfree(ethsw->ports); ++ +err_takedown: -+ ethsw_remove(sw_dev); ++ ethsw_takedown(sw_dev); ++ +err_free_cmdport: -+ fsl_mc_portal_free(priv->mc_io); -+err_free_netdev: ++ fsl_mc_portal_free(ethsw->mc_io); ++ ++err_free_drvdata: ++ kfree(ethsw); + dev_set_drvdata(dev, NULL); -+ free_netdev(netdev); + + return err; +} @@ -17128,23 +16473,117 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + .vendor = FSL_MC_VENDOR_FREESCALE, + .obj_type = "dpsw", + }, -+ {} ++ { .vendor = 0x0 } +}; ++MODULE_DEVICE_TABLE(fslmc, ethsw_match_id_table); + +static struct fsl_mc_driver eth_sw_drv = { + .driver = { -+ .name = KBUILD_MODNAME, -+ .owner = THIS_MODULE, ++ .name = KBUILD_MODNAME, ++ .owner = THIS_MODULE, + }, -+ .probe = ethsw_probe, -+ .remove = ethsw_remove, -+ .match_id_table = ethsw_match_id_table, ++ .probe = ethsw_probe, ++ .remove = ethsw_remove, ++ .match_id_table = ethsw_match_id_table +}; + +module_fsl_mc_driver(eth_sw_drv); + -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("DPAA2 Ethernet Switch Driver (prototype)"); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_DESCRIPTION("DPAA2 Ethernet Switch Driver"); +--- /dev/null ++++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.h +@@ -0,0 +1,90 @@ ++/* Copyright 2014-2017 Freescale Semiconductor Inc. ++ * Copyright 2017 NXP ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#ifndef __ETHSW_H ++#define __ETHSW_H ++ ++#include <linux/netdevice.h> ++#include <linux/etherdevice.h> ++#include <linux/rtnetlink.h> ++#include <linux/if_vlan.h> ++#include <uapi/linux/if_bridge.h> ++#include <net/switchdev.h> ++#include <linux/if_bridge.h> ++ ++#include "dpsw.h" ++ ++/* Number of IRQs supported */ ++#define DPSW_IRQ_NUM 2 ++ ++#define ETHSW_VLAN_MEMBER 1 ++#define ETHSW_VLAN_UNTAGGED 2 ++#define ETHSW_VLAN_PVID 4 ++#define ETHSW_VLAN_GLOBAL 8 ++ ++/* Maximum Frame Length supported by HW (currently 10k) */ ++#define DPAA2_MFL (10 * 1024) ++#define ETHSW_MAX_FRAME_LENGTH (DPAA2_MFL - VLAN_ETH_HLEN - ETH_FCS_LEN) ++#define ETHSW_L2_MAX_FRM(mtu) ((mtu) + VLAN_ETH_HLEN + ETH_FCS_LEN) ++ ++extern const struct ethtool_ops ethsw_port_ethtool_ops; ++ ++struct ethsw_core; ++ ++/* Per port private data */ ++struct ethsw_port_priv { ++ struct net_device *netdev; ++ u16 idx; ++ struct ethsw_core *ethsw_data; ++ u8 link_state; ++ u8 stp_state; ++ bool flood; ++ ++ u8 vlans[VLAN_VID_MASK + 1]; ++ u16 pvid; ++}; ++ ++/* Switch data */ ++struct ethsw_core { ++ struct device *dev; ++ struct fsl_mc_io *mc_io; ++ u16 dpsw_handle; ++ struct dpsw_attr sw_attr; ++ int dev_id; ++ struct ethsw_port_priv **ports; ++ ++ u8 vlans[VLAN_VID_MASK + 1]; ++ bool learning; ++}; ++ ++#endif /* __ETHSW_H */ --- /dev/null +++ b/drivers/staging/fsl-dpaa2/evb/Kconfig @@ -0,0 +1,7 @@ @@ -17452,7 +16891,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#endif /* _FSL_DPDMUX_CMD_H */ --- /dev/null +++ b/drivers/staging/fsl-dpaa2/evb/dpdmux.c -@@ -0,0 +1,1112 @@ +@@ -0,0 +1,1111 @@ +/* Copyright 2013-2016 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without @@ -17484,8 +16923,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ -+#include "../../fsl-mc/include/mc-sys.h" -+#include "../../fsl-mc/include/mc-cmd.h" ++#include <linux/fsl/mc.h> +#include "dpdmux.h" +#include "dpdmux-cmd.h" + @@ -17511,7 +16949,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + int dpdmux_id, + u16 *token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpdmux_cmd_open *cmd_params; + int err; + @@ -17548,7 +16986,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u16 token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_CLOSE, @@ -17587,7 +17025,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + const struct dpdmux_cfg *cfg, + u32 *obj_id) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpdmux_cmd_create *cmd_params; + int err; + @@ -17636,7 +17074,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u32 object_id) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpdmux_cmd_destroy *cmd_params; + + /* prepare command */ @@ -17662,7 +17100,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u16 token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_ENABLE, @@ -17685,7 +17123,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u16 token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_DISABLE, @@ -17710,7 +17148,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + int *en) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpdmux_rsp_is_enabled *rsp_params; + int err; + @@ -17743,7 +17181,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u16 token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_RESET, @@ -17775,7 +17213,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 irq_index, + u8 en) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpdmux_cmd_set_irq_enable *cmd_params; + + /* prepare command */ @@ -17806,7 +17244,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 irq_index, + u8 *en) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpdmux_cmd_get_irq_enable *cmd_params; + struct dpdmux_rsp_get_irq_enable *rsp_params; + int err; @@ -17852,7 +17290,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 irq_index, + u32 mask) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpdmux_cmd_set_irq_mask *cmd_params; + + /* prepare command */ @@ -17886,7 +17324,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 irq_index, + u32 *mask) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpdmux_cmd_get_irq_mask *cmd_params; + struct dpdmux_rsp_get_irq_mask *rsp_params; + int err; @@ -17928,7 +17366,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 irq_index, + u32 *status) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpdmux_cmd_get_irq_status *cmd_params; + struct dpdmux_rsp_get_irq_status *rsp_params; + int err; @@ -17971,7 +17409,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 irq_index, + u32 status) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpdmux_cmd_clear_irq_status *cmd_params; + + /* prepare command */ @@ -18000,7 +17438,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + struct dpdmux_attr *attr) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpdmux_rsp_get_attr *rsp_params; + int err; + @@ -18041,7 +17479,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 if_id) +{ + struct dpdmux_cmd_if *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_ENABLE, @@ -18069,7 +17507,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 if_id) +{ + struct dpdmux_cmd_if *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_DISABLE, @@ -18101,7 +17539,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 token, + u16 max_frame_length) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpdmux_cmd_set_max_frame_length *cmd_params; + + /* prepare command */ @@ -18127,7 +17565,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u16 token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_UL_RESET_COUNTERS, @@ -18161,7 +17599,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 if_id, + const struct dpdmux_accepted_frames *cfg) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpdmux_cmd_if_set_accepted_frames *cmd_params; + + /* prepare command */ @@ -18195,7 +17633,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 if_id, + struct dpdmux_if_attr *attr) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpdmux_cmd_if *cmd_params; + struct dpdmux_rsp_if_get_attr *rsp_params; + int err; @@ -18242,7 +17680,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 if_id, + const struct dpdmux_l2_rule *rule) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpdmux_cmd_if_l2_rule *cmd_params; + + /* prepare command */ @@ -18282,7 +17720,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 if_id, + const struct dpdmux_l2_rule *rule) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpdmux_cmd_if_l2_rule *cmd_params; + + /* prepare command */ @@ -18321,7 +17759,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + enum dpdmux_counter_type counter_type, + u64 *counter) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpdmux_cmd_if_get_counter *cmd_params; + struct dpdmux_rsp_if_get_counter *rsp_params; + int err; @@ -18362,7 +17800,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 if_id, + struct dpdmux_link_cfg *cfg) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpdmux_cmd_if_set_link_cfg *cmd_params; + + /* prepare command */ @@ -18394,7 +17832,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 if_id, + struct dpdmux_link_state *state) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpdmux_cmd_if_get_link_state *cmd_params; + struct dpdmux_rsp_if_get_link_state *rsp_params; + int err; @@ -18445,7 +17883,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u64 key_cfg_iova) +{ + struct dpdmux_set_custom_key *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_SET_CUSTOM_KEY, @@ -18481,7 +17919,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct dpdmux_cls_action *action) +{ + struct dpdmux_cmd_add_custom_cls_entry *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_ADD_CUSTOM_CLS_ENTRY, @@ -18518,7 +17956,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct dpdmux_rule_cfg *rule) +{ + struct dpdmux_cmd_remove_custom_cls_entry *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_REMOVE_CUSTOM_CLS_ENTRY, @@ -18547,7 +17985,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 *major_ver, + u16 *minor_ver) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpdmux_rsp_get_api_version *rsp_params; + int err; + @@ -19023,7 +18461,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#endif /* __FSL_DPDMUX_H */ --- /dev/null +++ b/drivers/staging/fsl-dpaa2/evb/evb.c -@@ -0,0 +1,1350 @@ +@@ -0,0 +1,1354 @@ +/* Copyright 2015 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without @@ -19064,7 +18502,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#include <uapi/linux/if_bridge.h> +#include <net/netlink.h> + -+#include "../../fsl-mc/include/mc.h" ++#include <linux/fsl/mc.h> + +#include "dpdmux.h" +#include "dpdmux-cmd.h" @@ -19079,9 +18517,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#define DPDMUX_MAX_IRQ_NUM 2 + +/* MAX FRAME LENGTH (currently 10k) */ -+#define EVB_MAX_FRAME_LENGTH (10 * 1024) -+/* MIN FRAME LENGTH (64 bytes + 4 bytes CRC) */ -+#define EVB_MIN_FRAME_LENGTH 68 ++#define EVB_MAX_FRAME_LENGTH (10 * 1024) ++#define EVB_MAX_MTU (EVB_MAX_FRAME_LENGTH - VLAN_ETH_HLEN) ++#define EVB_MIN_MTU 68 + +struct evb_port_priv { + struct net_device *netdev; @@ -19482,16 +18920,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + if (port_priv->port_index > 0) + return -EPERM; + -+ if (mtu < EVB_MIN_FRAME_LENGTH || mtu > EVB_MAX_FRAME_LENGTH) { -+ netdev_err(netdev, "Invalid MTU %d. Valid range is: %d..%d\n", -+ mtu, EVB_MIN_FRAME_LENGTH, EVB_MAX_FRAME_LENGTH); -+ return -EINVAL; -+ } -+ + err = dpdmux_set_max_frame_length(evb_priv->mc_io, + 0, + evb_priv->mux_handle, -+ (uint16_t)mtu); ++ (uint16_t)(mtu + VLAN_ETH_HLEN)); + + if (unlikely(err)) { + netdev_err(netdev, "dpdmux_ul_set_max_frame_length err %d\n", @@ -19872,6 +19304,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +error: + netdev_err(netdev, "dpdmux_if_get_counter err %d\n", err); ++ return storage; +} + +static const struct net_device_ops evb_port_ops = { @@ -20234,11 +19667,16 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + priv = netdev_priv(netdev); + -+ err = fsl_mc_portal_allocate(evb_dev, 0, &priv->mc_io); -+ if (unlikely(err)) { -+ dev_err(dev, "fsl_mc_portal_allocate err %d\n", err); ++ err = fsl_mc_portal_allocate(evb_dev, FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, ++ &priv->mc_io); ++ if (err) { ++ if (err == -ENXIO) ++ err = -EPROBE_DEFER; ++ else ++ dev_err(dev, "fsl_mc_portal_allocate err %d\n", err); + goto err_free_netdev; + } ++ + if (!priv->mc_io) { + dev_err(dev, "fsl_mc_portal_allocate returned null handle but no error\n"); + err = -EFAULT; @@ -20315,6 +19753,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + list_add(&port_priv->list, &priv->port_list); + } else { ++ /* Set MTU limits only on uplink */ ++ port_netdev->min_mtu = EVB_MIN_MTU; ++ port_netdev->max_mtu = EVB_MAX_MTU; ++ + err = register_netdev(netdev); + + if (err < 0) { @@ -20590,7 +20032,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#endif /* _FSL_DPMAC_CMD_H */ --- /dev/null +++ b/drivers/staging/fsl-dpaa2/mac/dpmac.c -@@ -0,0 +1,620 @@ +@@ -0,0 +1,619 @@ +/* Copyright 2013-2016 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without @@ -20622,8 +20064,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ -+#include "../../fsl-mc/include/mc-sys.h" -+#include "../../fsl-mc/include/mc-cmd.h" ++#include <linux/fsl/mc.h> +#include "dpmac.h" +#include "dpmac-cmd.h" + @@ -20650,7 +20091,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 *token) +{ + struct dpmac_cmd_open *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ @@ -20686,7 +20127,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 cmd_flags, + u16 token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLOSE, cmd_flags, @@ -20722,7 +20163,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 *obj_id) +{ + struct dpmac_cmd_create *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ @@ -20764,7 +20205,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 object_id) +{ + struct dpmac_cmd_destroy *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_DESTROY, @@ -20799,7 +20240,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 en) +{ + struct dpmac_cmd_set_irq_enable *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ_ENABLE, @@ -20831,7 +20272,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +{ + struct dpmac_cmd_get_irq_enable *cmd_params; + struct dpmac_rsp_get_irq_enable *rsp_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ @@ -20876,7 +20317,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 mask) +{ + struct dpmac_cmd_set_irq_mask *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ_MASK, @@ -20911,7 +20352,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +{ + struct dpmac_cmd_get_irq_mask *cmd_params; + struct dpmac_rsp_get_irq_mask *rsp_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ @@ -20954,7 +20395,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +{ + struct dpmac_cmd_get_irq_status *cmd_params; + struct dpmac_rsp_get_irq_status *rsp_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ @@ -20997,7 +20438,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 status) +{ + struct dpmac_cmd_clear_irq_status *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLEAR_IRQ_STATUS, @@ -21027,7 +20468,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct dpmac_attr *attr) +{ + struct dpmac_rsp_get_attributes *rsp_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ @@ -21065,7 +20506,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct dpmac_link_cfg *cfg) +{ + struct dpmac_rsp_get_link_cfg *rsp_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err = 0; + + /* prepare command */ @@ -21100,7 +20541,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct dpmac_link_state *link_state) +{ + struct dpmac_cmd_set_link_state *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_LINK_STATE, @@ -21133,7 +20574,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +{ + struct dpmac_cmd_get_counter *dpmac_cmd; + struct dpmac_rsp_get_counter *dpmac_rsp; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err = 0; + + /* prepare command */ @@ -21161,7 +20602,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + const u8 addr[6]) +{ + struct dpmac_cmd_set_port_mac_addr *dpmac_cmd; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_PORT_MAC_ADDR, @@ -21194,7 +20635,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 *minor_ver) +{ + struct dpmac_rsp_get_api_version *rsp_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_API_VERSION, @@ -21558,7 +20999,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#endif /* __FSL_DPMAC_H */ --- /dev/null +++ b/drivers/staging/fsl-dpaa2/mac/mac.c -@@ -0,0 +1,670 @@ +@@ -0,0 +1,673 @@ +/* Copyright 2015 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without @@ -21607,8 +21048,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#include <linux/phy.h> +#include <linux/phy_fixed.h> + -+#include "../../fsl-mc/include/mc.h" -+#include "../../fsl-mc/include/mc-sys.h" ++#include <linux/fsl/mc.h> + +#include "dpmac.h" +#include "dpmac-cmd.h" @@ -21713,16 +21153,18 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return NETDEV_TX_OK; +} + -+static int dpaa2_mac_get_settings(struct net_device *netdev, -+ struct ethtool_cmd *cmd) ++static int dpaa2_mac_get_link_ksettings(struct net_device *netdev, ++ struct ethtool_link_ksettings *ks) +{ -+ return phy_ethtool_gset(netdev->phydev, cmd); ++ phy_ethtool_ksettings_get(netdev->phydev, ks); ++ ++ return 0; +} + -+static int dpaa2_mac_set_settings(struct net_device *netdev, -+ struct ethtool_cmd *cmd) ++static int dpaa2_mac_set_link_ksettings(struct net_device *netdev, ++ const struct ethtool_link_ksettings *ks) +{ -+ return phy_ethtool_sset(netdev->phydev, cmd); ++ return phy_ethtool_ksettings_set(netdev->phydev, ks); +} + +static struct rtnl_link_stats64 *dpaa2_mac_get_stats(struct net_device *netdev, @@ -21881,8 +21323,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; + +static const struct ethtool_ops dpaa2_mac_ethtool_ops = { -+ .get_settings = &dpaa2_mac_get_settings, -+ .set_settings = &dpaa2_mac_set_settings, ++ .get_link_ksettings = &dpaa2_mac_get_link_ksettings, ++ .set_link_ksettings = &dpaa2_mac_set_link_ksettings, + .get_strings = &dpaa2_mac_get_strings, + .get_ethtool_stats = &dpaa2_mac_get_ethtool_stats, + .get_sset_count = &dpaa2_mac_get_sset_count, @@ -22051,10 +21493,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + dev_set_drvdata(dev, priv); + -+ err = fsl_mc_portal_allocate(mc_dev, 0, &mc_dev->mc_io); ++ /* We may need to issue MC commands while in atomic context */ ++ err = fsl_mc_portal_allocate(mc_dev, FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, ++ &mc_dev->mc_io); + if (err || !mc_dev->mc_io) { -+ dev_err(dev, "fsl_mc_portal_allocate error: %d\n", err); -+ err = -ENODEV; ++ dev_dbg(dev, "fsl_mc_portal_allocate error: %d\n", err); ++ err = -EPROBE_DEFER; + goto err_free_netdev; + } + @@ -22439,8 +21883,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ -+#include "../../fsl-mc/include/mc-sys.h" -+#include "../../fsl-mc/include/mc-cmd.h" ++#include <linux/fsl/mc.h> ++ +#include "dprtc.h" +#include "dprtc-cmd.h" + @@ -22467,7 +21911,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint16_t *token) +{ + struct dprtc_cmd_open *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ @@ -22503,7 +21947,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint32_t cmd_flags, + uint16_t token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_CLOSE, cmd_flags, @@ -22538,7 +21982,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + const struct dprtc_cfg *cfg, + uint32_t *obj_id) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + + (void)(cfg); /* unused */ @@ -22580,7 +22024,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint32_t object_id) +{ + struct dprtc_cmd_destroy *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_DESTROY, @@ -22597,7 +22041,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint32_t cmd_flags, + uint16_t token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_ENABLE, cmd_flags, @@ -22611,7 +22055,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint32_t cmd_flags, + uint16_t token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_DISABLE, @@ -22628,7 +22072,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + int *en) +{ + struct dprtc_rsp_is_enabled *rsp_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ @@ -22651,7 +22095,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint32_t cmd_flags, + uint16_t token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_RESET, @@ -22684,7 +22128,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint8_t en) +{ + struct dprtc_cmd_set_irq_enable *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_IRQ_ENABLE, @@ -22716,7 +22160,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +{ + struct dprtc_rsp_get_irq_enable *rsp_params; + struct dprtc_cmd_get_irq *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ @@ -22761,7 +22205,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint32_t mask) +{ + struct dprtc_cmd_set_irq_mask *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_IRQ_MASK, @@ -22796,7 +22240,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +{ + struct dprtc_rsp_get_irq_mask *rsp_params; + struct dprtc_cmd_get_irq *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ @@ -22839,7 +22283,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +{ + struct dprtc_cmd_get_irq_status *cmd_params; + struct dprtc_rsp_get_irq_status *rsp_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ @@ -22882,7 +22326,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint32_t status) +{ + struct dprtc_cmd_clear_irq_status *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_CLEAR_IRQ_STATUS, @@ -22912,7 +22356,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct dprtc_attr *attr) +{ + struct dprtc_rsp_get_attributes *rsp_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ @@ -22949,7 +22393,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + int64_t offset) +{ + struct dprtc_cmd_set_clock_offset *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_CLOCK_OFFSET, @@ -22978,7 +22422,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint32_t freq_compensation) +{ + struct dprtc_get_freq_compensation *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_FREQ_COMPENSATION, @@ -23007,7 +22451,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint32_t *freq_compensation) +{ + struct dprtc_get_freq_compensation *rsp_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ @@ -23043,7 +22487,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint64_t *time) +{ + struct dprtc_time *rsp_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ @@ -23079,7 +22523,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint64_t time) +{ + struct dprtc_time *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_TIME, @@ -23109,7 +22553,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint16_t token, uint64_t time) +{ + struct dprtc_time *cmd_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_ALARM, @@ -23137,7 +22581,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint16_t *minor_ver) +{ + struct dprtc_rsp_get_api_version *rsp_params; -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_API_VERSION, @@ -23331,7 +22775,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#endif /* __FSL_DPRTC_H */ --- /dev/null +++ b/drivers/staging/fsl-dpaa2/rtc/rtc.c -@@ -0,0 +1,243 @@ +@@ -0,0 +1,242 @@ +/* Copyright 2013-2015 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without @@ -23367,8 +22811,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#include <linux/module.h> +#include <linux/ptp_clock_kernel.h> + -+#include "../../fsl-mc/include/mc.h" -+#include "../../fsl-mc/include/mc-sys.h" ++#include <linux/fsl/mc.h> + +#include "dprtc.h" +#include "dprtc-cmd.h" @@ -23575,3 +23018,21 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("DPAA2 RTC (PTP 1588 clock) driver (prototype)"); +--- a/include/linux/filter.h ++++ b/include/linux/filter.h +@@ -429,12 +429,15 @@ struct sk_filter { + + struct bpf_skb_data_end { + struct qdisc_skb_cb qdisc_cb; ++ void *data_meta; + void *data_end; + }; + + struct xdp_buff { + void *data; + void *data_end; ++ void *data_meta; ++ void *data_hard_start; + }; + + /* compute the linear packet data range [data, data_end) which diff --git a/target/linux/layerscape/patches-4.9/706-fsl_ppfe-support-layercape.patch b/target/linux/layerscape/patches-4.9/706-fsl_ppfe-support-layercape.patch index 01a24336f6..e71c85c7f5 100644 --- a/target/linux/layerscape/patches-4.9/706-fsl_ppfe-support-layercape.patch +++ b/target/linux/layerscape/patches-4.9/706-fsl_ppfe-support-layercape.patch @@ -1,48 +1,48 @@ -From 79fb41b6040d00d3bdfca9eb70a7848441eb7447 Mon Sep 17 00:00:00 2001 +From 50fb2f2e93aeae0baed156eb4794a2f358376b77 Mon Sep 17 00:00:00 2001 From: Yangbo Lu <yangbo.lu@nxp.com> -Date: Wed, 17 Jan 2018 15:14:12 +0800 -Subject: [PATCH] fsl_ppfe: support layercape +Date: Thu, 5 Jul 2018 17:19:20 +0800 +Subject: [PATCH 12/32] fsl_ppfe: support layercape This is an integrated patch for layerscape pfe support. Calvin Johnson <calvin.johnson@nxp.com> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- - drivers/staging/fsl_ppfe/Kconfig | 20 + - drivers/staging/fsl_ppfe/Makefile | 19 + - drivers/staging/fsl_ppfe/TODO | 2 + - drivers/staging/fsl_ppfe/include/pfe/cbus.h | 78 + - drivers/staging/fsl_ppfe/include/pfe/cbus/bmu.h | 55 + - .../staging/fsl_ppfe/include/pfe/cbus/class_csr.h | 289 +++ - .../staging/fsl_ppfe/include/pfe/cbus/emac_mtip.h | 242 ++ - drivers/staging/fsl_ppfe/include/pfe/cbus/gpi.h | 86 + - drivers/staging/fsl_ppfe/include/pfe/cbus/hif.h | 100 + - .../staging/fsl_ppfe/include/pfe/cbus/hif_nocpy.h | 50 + - .../staging/fsl_ppfe/include/pfe/cbus/tmu_csr.h | 168 ++ - .../staging/fsl_ppfe/include/pfe/cbus/util_csr.h | 61 + - drivers/staging/fsl_ppfe/include/pfe/pfe.h | 372 +++ - drivers/staging/fsl_ppfe/pfe_ctrl.c | 238 ++ - drivers/staging/fsl_ppfe/pfe_ctrl.h | 112 + - drivers/staging/fsl_ppfe/pfe_debugfs.c | 111 + - drivers/staging/fsl_ppfe/pfe_debugfs.h | 25 + - drivers/staging/fsl_ppfe/pfe_eth.c | 2474 ++++++++++++++++++++ - drivers/staging/fsl_ppfe/pfe_eth.h | 184 ++ - drivers/staging/fsl_ppfe/pfe_firmware.c | 314 +++ - drivers/staging/fsl_ppfe/pfe_firmware.h | 32 + - drivers/staging/fsl_ppfe/pfe_hal.c | 1516 ++++++++++++ - drivers/staging/fsl_ppfe/pfe_hif.c | 1072 +++++++++ - drivers/staging/fsl_ppfe/pfe_hif.h | 211 ++ - drivers/staging/fsl_ppfe/pfe_hif_lib.c | 637 +++++ - drivers/staging/fsl_ppfe/pfe_hif_lib.h | 240 ++ - drivers/staging/fsl_ppfe/pfe_hw.c | 176 ++ - drivers/staging/fsl_ppfe/pfe_hw.h | 27 + - drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c | 385 +++ - drivers/staging/fsl_ppfe/pfe_mod.c | 141 ++ - drivers/staging/fsl_ppfe/pfe_mod.h | 112 + - drivers/staging/fsl_ppfe/pfe_perfmon.h | 38 + - drivers/staging/fsl_ppfe/pfe_sysfs.c | 818 +++++++ - drivers/staging/fsl_ppfe/pfe_sysfs.h | 29 + - 34 files changed, 10434 insertions(+) + drivers/staging/fsl_ppfe/Kconfig | 20 + + drivers/staging/fsl_ppfe/Makefile | 19 + + drivers/staging/fsl_ppfe/TODO | 2 + + drivers/staging/fsl_ppfe/include/pfe/cbus.h | 78 + + .../staging/fsl_ppfe/include/pfe/cbus/bmu.h | 55 + + .../fsl_ppfe/include/pfe/cbus/class_csr.h | 289 ++ + .../fsl_ppfe/include/pfe/cbus/emac_mtip.h | 242 ++ + .../staging/fsl_ppfe/include/pfe/cbus/gpi.h | 86 + + .../staging/fsl_ppfe/include/pfe/cbus/hif.h | 100 + + .../fsl_ppfe/include/pfe/cbus/hif_nocpy.h | 50 + + .../fsl_ppfe/include/pfe/cbus/tmu_csr.h | 168 ++ + .../fsl_ppfe/include/pfe/cbus/util_csr.h | 61 + + drivers/staging/fsl_ppfe/include/pfe/pfe.h | 372 +++ + drivers/staging/fsl_ppfe/pfe_ctrl.c | 238 ++ + drivers/staging/fsl_ppfe/pfe_ctrl.h | 112 + + drivers/staging/fsl_ppfe/pfe_debugfs.c | 111 + + drivers/staging/fsl_ppfe/pfe_debugfs.h | 25 + + drivers/staging/fsl_ppfe/pfe_eth.c | 2491 +++++++++++++++++ + drivers/staging/fsl_ppfe/pfe_eth.h | 184 ++ + drivers/staging/fsl_ppfe/pfe_firmware.c | 314 +++ + drivers/staging/fsl_ppfe/pfe_firmware.h | 32 + + drivers/staging/fsl_ppfe/pfe_hal.c | 1516 ++++++++++ + drivers/staging/fsl_ppfe/pfe_hif.c | 1072 +++++++ + drivers/staging/fsl_ppfe/pfe_hif.h | 211 ++ + drivers/staging/fsl_ppfe/pfe_hif_lib.c | 640 +++++ + drivers/staging/fsl_ppfe/pfe_hif_lib.h | 241 ++ + drivers/staging/fsl_ppfe/pfe_hw.c | 176 ++ + drivers/staging/fsl_ppfe/pfe_hw.h | 27 + + .../staging/fsl_ppfe/pfe_ls1012a_platform.c | 385 +++ + drivers/staging/fsl_ppfe/pfe_mod.c | 156 ++ + drivers/staging/fsl_ppfe/pfe_mod.h | 114 + + drivers/staging/fsl_ppfe/pfe_perfmon.h | 38 + + drivers/staging/fsl_ppfe/pfe_sysfs.c | 818 ++++++ + drivers/staging/fsl_ppfe/pfe_sysfs.h | 29 + + 34 files changed, 10472 insertions(+) create mode 100644 drivers/staging/fsl_ppfe/Kconfig create mode 100644 drivers/staging/fsl_ppfe/Makefile create mode 100644 drivers/staging/fsl_ppfe/TODO @@ -2159,7 +2159,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#endif /* _PFE_DEBUGFS_H_ */ --- /dev/null +++ b/drivers/staging/fsl_ppfe/pfe_eth.c -@@ -0,0 +1,2474 @@ +@@ -0,0 +1,2491 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP @@ -4457,6 +4457,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + goto err0; + } + ++ if (us) ++ emac_txq_cnt = EMAC_TXQ_CNT; + /* Create an ethernet device instance */ + ndev = alloc_etherdev_mq(sizeof(*priv), emac_txq_cnt); + @@ -4503,6 +4505,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + } + } + ++ if (us) ++ goto phy_init; ++ + ndev->mtu = 1500; + + /* Set MTU limits */ @@ -4542,6 +4547,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + netdev_err(ndev, "register_netdev() failed\n"); + goto err3; + } ++ ++phy_init: + device_init_wakeup(&ndev->dev, WAKE_MAGIC); + + if (!(priv->einfo->phy_flags & GEMAC_NO_PHY)) { @@ -4553,6 +4560,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + } + } + ++ if (us) { ++ if (priv->phydev) ++ phy_start(priv->phydev); ++ return 0; ++ } ++ + netif_carrier_on(ndev); + + /* Create all the sysfs files */ @@ -4564,6 +4577,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + return 0; +err4: ++ if (us) ++ goto err3; + unregister_netdev(ndev); +err3: + pfe_eth_mdio_exit(priv->mii_bus); @@ -4610,13 +4625,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +{ + netif_info(priv, probe, priv->ndev, "%s\n", __func__); + -+ pfe_eth_sysfs_exit(priv->ndev); -+ -+ unregister_netdev(priv->ndev); ++ if (!us) ++ pfe_eth_sysfs_exit(priv->ndev); + + if (!(priv->einfo->phy_flags & GEMAC_NO_PHY)) + pfe_phy_exit(priv->ndev); + ++ if (!us) ++ unregister_netdev(priv->ndev); ++ + if (priv->mii_bus) + pfe_eth_mdio_exit(priv->mii_bus); + @@ -7983,7 +8000,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#endif /* _PFE_HIF_H_ */ --- /dev/null +++ b/drivers/staging/fsl_ppfe/pfe_hif_lib.c -@@ -0,0 +1,637 @@ +@@ -0,0 +1,640 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP @@ -8421,6 +8438,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u16 size = *rx_ctrl >> HIF_CTRL_RX_OFFSET_OFST; + + if (size) { ++ size += PFE_PARSE_INFO_SIZE; + *len = CL_DESC_BUF_LEN(desc->ctrl) - + PFE_PKT_HEADER_SZ - size; + *ofst = pfe_pkt_headroom + PFE_PKT_HEADER_SZ @@ -8428,8 +8446,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + *priv_data = desc->data + PFE_PKT_HEADER_SZ; + } else { + *len = CL_DESC_BUF_LEN(desc->ctrl) - -+ PFE_PKT_HEADER_SZ; -+ *ofst = pfe_pkt_headroom + PFE_PKT_HEADER_SZ; ++ PFE_PKT_HEADER_SZ - PFE_PARSE_INFO_SIZE; ++ *ofst = pfe_pkt_headroom ++ + PFE_PKT_HEADER_SZ ++ + PFE_PARSE_INFO_SIZE; + *priv_data = NULL; + } + @@ -8623,7 +8643,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +} --- /dev/null +++ b/drivers/staging/fsl_ppfe/pfe_hif_lib.h -@@ -0,0 +1,240 @@ +@@ -0,0 +1,241 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP @@ -8649,6 +8669,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +#define HIF_CL_REQ_TIMEOUT 10 +#define GFP_DMA_PFE 0 ++#define PFE_PARSE_INFO_SIZE 16 + +enum { + REQUEST_CL_REGISTER = 0, @@ -8772,7 +8793,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#define PFE_BUF_SIZE 2048 +#define PFE_PKT_HEADROOM 128 + -+#define SKB_SHARED_INFO_SIZE (sizeof(struct skb_shared_info)) ++#define SKB_SHARED_INFO_SIZE SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) +#define PFE_PKT_SIZE (PFE_BUF_SIZE - PFE_PKT_HEADROOM \ + - SKB_SHARED_INFO_SIZE) +#define MAX_L2_HDR_SIZE 14 /* Not correct for VLAN/PPPoE */ @@ -9463,7 +9484,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +MODULE_AUTHOR("NXP DNCPE"); --- /dev/null +++ b/drivers/staging/fsl_ppfe/pfe_mod.c -@@ -0,0 +1,141 @@ +@@ -0,0 +1,156 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP @@ -9485,6 +9506,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#include <linux/dma-mapping.h> +#include "pfe_mod.h" + ++unsigned int us; ++module_param(us, uint, 0444); ++MODULE_PARM_DESC(us, "0: module enabled for kernel networking (DEFAULT)\n" ++ "1: module enabled for userspace networking\n"); +struct pfe *pfe; + +/* @@ -9522,6 +9547,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + if (rc < 0) + goto err_hw; + ++ if (us) ++ goto firmware_init; ++ + rc = pfe_hif_lib_init(pfe); + if (rc < 0) + goto err_hif_lib; @@ -9530,6 +9558,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + if (rc < 0) + goto err_hif; + ++firmware_init: + rc = pfe_firmware_init(pfe); + if (rc < 0) + goto err_firmware; @@ -9565,6 +9594,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + pfe_firmware_exit(pfe); + +err_firmware: ++ if (us) ++ goto err_hif_lib; ++ + pfe_hif_exit(pfe); + +err_hif: @@ -9597,17 +9629,21 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#endif + pfe_firmware_exit(pfe); + ++ if (us) ++ goto hw_exit; ++ + pfe_hif_exit(pfe); + + pfe_hif_lib_exit(pfe); + ++hw_exit: + pfe_hw_exit(pfe); + + return 0; +} --- /dev/null +++ b/drivers/staging/fsl_ppfe/pfe_mod.h -@@ -0,0 +1,112 @@ +@@ -0,0 +1,114 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP @@ -9632,6 +9668,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#include <linux/device.h> +#include <linux/elf.h> + ++extern unsigned int us; ++ +struct pfe; + +#include "pfe_hw.h" diff --git a/target/linux/layerscape/patches-4.9/803-cpufreq-support-layerscape.patch b/target/linux/layerscape/patches-4.9/803-cpufreq-support-layerscape.patch index ac9b4b068a..cf2b42a547 100644 --- a/target/linux/layerscape/patches-4.9/803-cpufreq-support-layerscape.patch +++ b/target/linux/layerscape/patches-4.9/803-cpufreq-support-layerscape.patch @@ -1,20 +1,111 @@ -From b018e44a68dc2f4df819ae194e39e07313841dad Mon Sep 17 00:00:00 2001 +From d78d78ccbaded757e8bea0d13c4120518bdd4660 Mon Sep 17 00:00:00 2001 From: Yangbo Lu <yangbo.lu@nxp.com> -Date: Wed, 17 Jan 2018 15:27:58 +0800 -Subject: [PATCH 15/30] cpufreq: support layerscape +Date: Thu, 5 Jul 2018 17:21:38 +0800 +Subject: [PATCH 15/32] cpufreq: support layerscape This is an integrated patch for layerscape pm support. Signed-off-by: Tang Yuantian <Yuantian.Tang@nxp.com> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- - drivers/cpufreq/Kconfig | 2 +- - drivers/cpufreq/qoriq-cpufreq.c | 176 +++++++++++++++------------------------- - drivers/firmware/psci.c | 12 ++- - drivers/soc/fsl/rcpm.c | 158 ++++++++++++++++++++++++++++++++++++ - 4 files changed, 235 insertions(+), 113 deletions(-) + .../devicetree/bindings/powerpc/fsl/pmc.txt | 59 ++-- + drivers/cpufreq/Kconfig | 2 +- + drivers/cpufreq/qoriq-cpufreq.c | 176 +++++------ + drivers/firmware/psci.c | 12 +- + drivers/soc/fsl/rcpm.c | 158 ++++++++++ + drivers/soc/fsl/sleep_fsm.c | 279 ++++++++++++++++++ + drivers/soc/fsl/sleep_fsm.h | 130 ++++++++ + 7 files changed, 678 insertions(+), 138 deletions(-) create mode 100644 drivers/soc/fsl/rcpm.c + create mode 100644 drivers/soc/fsl/sleep_fsm.c + create mode 100644 drivers/soc/fsl/sleep_fsm.h +--- a/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt ++++ b/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt +@@ -9,15 +9,20 @@ Properties: + + "fsl,mpc8548-pmc" should be listed for any chip whose PMC is + compatible. "fsl,mpc8536-pmc" should also be listed for any chip +- whose PMC is compatible, and implies deep-sleep capability. ++ whose PMC is compatible, and implies deep-sleep capability and ++ wake on user defined packet(wakeup on ARP). ++ ++ "fsl,p1022-pmc" should be listed for any chip whose PMC is ++ compatible, and implies lossless Ethernet capability during sleep. + + "fsl,mpc8641d-pmc" should be listed for any chip whose PMC is + compatible; all statements below that apply to "fsl,mpc8548-pmc" also + apply to "fsl,mpc8641d-pmc". + + Compatibility does not include bit assignments in SCCR/PMCDR/DEVDISR; these +- bit assignments are indicated via the sleep specifier in each device's +- sleep property. ++ bit assignments are indicated via the clock nodes. Device which has a ++ controllable clock source should have a "fsl,pmc-handle" property pointing ++ to the clock node. + + - reg: For devices compatible with "fsl,mpc8349-pmc", the first resource + is the PMC block, and the second resource is the Clock Configuration +@@ -33,31 +38,35 @@ Properties: + this is a phandle to an "fsl,gtm" node on which timer 4 can be used as + a wakeup source from deep sleep. + +-Sleep specifiers: +- +- fsl,mpc8349-pmc: Sleep specifiers consist of one cell. For each bit +- that is set in the cell, the corresponding bit in SCCR will be saved +- and cleared on suspend, and restored on resume. This sleep controller +- supports disabling and resuming devices at any time. +- +- fsl,mpc8536-pmc: Sleep specifiers consist of three cells, the third of +- which will be ORed into PMCDR upon suspend, and cleared from PMCDR +- upon resume. The first two cells are as described for fsl,mpc8578-pmc. +- This sleep controller only supports disabling devices during system +- sleep, or permanently. +- +- fsl,mpc8548-pmc: Sleep specifiers consist of one or two cells, the +- first of which will be ORed into DEVDISR (and the second into +- DEVDISR2, if present -- this cell should be zero or absent if the +- hardware does not have DEVDISR2) upon a request for permanent device +- disabling. This sleep controller does not support configuring devices +- to disable during system sleep (unless supported by another compatible +- match), or dynamically. ++Clock nodes: ++The clock nodes are to describe the masks in PM controller registers for each ++soc clock. ++- fsl,pmcdr-mask: For "fsl,mpc8548-pmc"-compatible devices, the mask will be ++ ORed into PMCDR before suspend if the device using this clock is the wake-up ++ source and need to be running during low power mode; clear the mask if ++ otherwise. ++ ++- fsl,sccr-mask: For "fsl,mpc8349-pmc"-compatible devices, the corresponding ++ bit specified by the mask in SCCR will be saved and cleared on suspend, and ++ restored on resume. ++ ++- fsl,devdisr-mask: Contain one or two cells, depending on the availability of ++ DEVDISR2 register. For compatible devices, the mask will be ORed into DEVDISR ++ or DEVDISR2 when the clock should be permenently disabled. + + Example: + +- power@b00 { +- compatible = "fsl,mpc8313-pmc", "fsl,mpc8349-pmc"; +- reg = <0xb00 0x100 0xa00 0x100>; +- interrupts = <80 8>; ++ power@e0070 { ++ compatible = "fsl,mpc8536-pmc", "fsl,mpc8548-pmc"; ++ reg = <0xe0070 0x20>; ++ ++ etsec1_clk: soc-clk@24 { ++ fsl,pmcdr-mask = <0x00000080>; ++ }; ++ etsec2_clk: soc-clk@25 { ++ fsl,pmcdr-mask = <0x00000040>; ++ }; ++ etsec3_clk: soc-clk@26 { ++ fsl,pmcdr-mask = <0x00000020>; ++ }; + }; --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -334,7 +334,7 @@ endif @@ -522,3 +613,418 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +} + +subsys_initcall(layerscape_rcpm_init); +--- /dev/null ++++ b/drivers/soc/fsl/sleep_fsm.c +@@ -0,0 +1,279 @@ ++/* ++ * deep sleep FSM (finite-state machine) configuration ++ * ++ * Copyright 2018 NXP ++ * ++ * Author: Hongbo Zhang <hongbo.zhang@freescale.com> ++ * Chenhui Zhao <chenhui.zhao@freescale.com> ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/io.h> ++#include <linux/types.h> ++ ++#include "sleep_fsm.h" ++/* ++ * These values are from chip's reference manual. For example, ++ * the values for T1040 can be found in "8.4.3.8 Programming ++ * supporting deep sleep mode" of Chapter 8 "Run Control and ++ * Power Management (RCPM)". ++ * The default value can be applied to T104x, LS1021. ++ */ ++struct fsm_reg_vals epu_default_val[] = { ++ /* EPGCR (Event Processor Global Control Register) */ ++ {EPGCR, 0}, ++ /* EPECR (Event Processor Event Control Registers) */ ++ {EPECR0 + EPECR_STRIDE * 0, 0}, ++ {EPECR0 + EPECR_STRIDE * 1, 0}, ++ {EPECR0 + EPECR_STRIDE * 2, 0xF0004004}, ++ {EPECR0 + EPECR_STRIDE * 3, 0x80000084}, ++ {EPECR0 + EPECR_STRIDE * 4, 0x20000084}, ++ {EPECR0 + EPECR_STRIDE * 5, 0x08000004}, ++ {EPECR0 + EPECR_STRIDE * 6, 0x80000084}, ++ {EPECR0 + EPECR_STRIDE * 7, 0x80000084}, ++ {EPECR0 + EPECR_STRIDE * 8, 0x60000084}, ++ {EPECR0 + EPECR_STRIDE * 9, 0x08000084}, ++ {EPECR0 + EPECR_STRIDE * 10, 0x42000084}, ++ {EPECR0 + EPECR_STRIDE * 11, 0x90000084}, ++ {EPECR0 + EPECR_STRIDE * 12, 0x80000084}, ++ {EPECR0 + EPECR_STRIDE * 13, 0x08000084}, ++ {EPECR0 + EPECR_STRIDE * 14, 0x02000084}, ++ {EPECR0 + EPECR_STRIDE * 15, 0x00000004}, ++ /* ++ * EPEVTCR (Event Processor EVT Pin Control Registers) ++ * SCU8 triger EVT2, and SCU11 triger EVT9 ++ */ ++ {EPEVTCR0 + EPEVTCR_STRIDE * 0, 0}, ++ {EPEVTCR0 + EPEVTCR_STRIDE * 1, 0}, ++ {EPEVTCR0 + EPEVTCR_STRIDE * 2, 0x80000001}, ++ {EPEVTCR0 + EPEVTCR_STRIDE * 3, 0}, ++ {EPEVTCR0 + EPEVTCR_STRIDE * 4, 0}, ++ {EPEVTCR0 + EPEVTCR_STRIDE * 5, 0}, ++ {EPEVTCR0 + EPEVTCR_STRIDE * 6, 0}, ++ {EPEVTCR0 + EPEVTCR_STRIDE * 7, 0}, ++ {EPEVTCR0 + EPEVTCR_STRIDE * 8, 0}, ++ {EPEVTCR0 + EPEVTCR_STRIDE * 9, 0xB0000001}, ++ /* EPCMPR (Event Processor Counter Compare Registers) */ ++ {EPCMPR0 + EPCMPR_STRIDE * 0, 0}, ++ {EPCMPR0 + EPCMPR_STRIDE * 1, 0}, ++ {EPCMPR0 + EPCMPR_STRIDE * 2, 0x000000FF}, ++ {EPCMPR0 + EPCMPR_STRIDE * 3, 0}, ++ {EPCMPR0 + EPCMPR_STRIDE * 4, 0x000000FF}, ++ {EPCMPR0 + EPCMPR_STRIDE * 5, 0x00000020}, ++ {EPCMPR0 + EPCMPR_STRIDE * 6, 0}, ++ {EPCMPR0 + EPCMPR_STRIDE * 7, 0}, ++ {EPCMPR0 + EPCMPR_STRIDE * 8, 0x000000FF}, ++ {EPCMPR0 + EPCMPR_STRIDE * 9, 0x000000FF}, ++ {EPCMPR0 + EPCMPR_STRIDE * 10, 0x000000FF}, ++ {EPCMPR0 + EPCMPR_STRIDE * 11, 0x000000FF}, ++ {EPCMPR0 + EPCMPR_STRIDE * 12, 0x000000FF}, ++ {EPCMPR0 + EPCMPR_STRIDE * 13, 0}, ++ {EPCMPR0 + EPCMPR_STRIDE * 14, 0x000000FF}, ++ {EPCMPR0 + EPCMPR_STRIDE * 15, 0x000000FF}, ++ /* EPCCR (Event Processor Counter Control Registers) */ ++ {EPCCR0 + EPCCR_STRIDE * 0, 0}, ++ {EPCCR0 + EPCCR_STRIDE * 1, 0}, ++ {EPCCR0 + EPCCR_STRIDE * 2, 0x92840000}, ++ {EPCCR0 + EPCCR_STRIDE * 3, 0}, ++ {EPCCR0 + EPCCR_STRIDE * 4, 0x92840000}, ++ {EPCCR0 + EPCCR_STRIDE * 5, 0x92840000}, ++ {EPCCR0 + EPCCR_STRIDE * 6, 0}, ++ {EPCCR0 + EPCCR_STRIDE * 7, 0}, ++ {EPCCR0 + EPCCR_STRIDE * 8, 0x92840000}, ++ {EPCCR0 + EPCCR_STRIDE * 9, 0x92840000}, ++ {EPCCR0 + EPCCR_STRIDE * 10, 0x92840000}, ++ {EPCCR0 + EPCCR_STRIDE * 11, 0x92840000}, ++ {EPCCR0 + EPCCR_STRIDE * 12, 0x92840000}, ++ {EPCCR0 + EPCCR_STRIDE * 13, 0}, ++ {EPCCR0 + EPCCR_STRIDE * 14, 0x92840000}, ++ {EPCCR0 + EPCCR_STRIDE * 15, 0x92840000}, ++ /* EPSMCR (Event Processor SCU Mux Control Registers) */ ++ {EPSMCR0 + EPSMCR_STRIDE * 0, 0}, ++ {EPSMCR0 + EPSMCR_STRIDE * 1, 0}, ++ {EPSMCR0 + EPSMCR_STRIDE * 2, 0x6C700000}, ++ {EPSMCR0 + EPSMCR_STRIDE * 3, 0x2F000000}, ++ {EPSMCR0 + EPSMCR_STRIDE * 4, 0x002F0000}, ++ {EPSMCR0 + EPSMCR_STRIDE * 5, 0x00002E00}, ++ {EPSMCR0 + EPSMCR_STRIDE * 6, 0x7C000000}, ++ {EPSMCR0 + EPSMCR_STRIDE * 7, 0x30000000}, ++ {EPSMCR0 + EPSMCR_STRIDE * 8, 0x64300000}, ++ {EPSMCR0 + EPSMCR_STRIDE * 9, 0x00003000}, ++ {EPSMCR0 + EPSMCR_STRIDE * 10, 0x65000030}, ++ {EPSMCR0 + EPSMCR_STRIDE * 11, 0x31740000}, ++ {EPSMCR0 + EPSMCR_STRIDE * 12, 0x7F000000}, ++ {EPSMCR0 + EPSMCR_STRIDE * 13, 0x00003100}, ++ {EPSMCR0 + EPSMCR_STRIDE * 14, 0x00000031}, ++ {EPSMCR0 + EPSMCR_STRIDE * 15, 0x76000000}, ++ /* EPACR (Event Processor Action Control Registers) */ ++ {EPACR0 + EPACR_STRIDE * 0, 0}, ++ {EPACR0 + EPACR_STRIDE * 1, 0}, ++ {EPACR0 + EPACR_STRIDE * 2, 0}, ++ {EPACR0 + EPACR_STRIDE * 3, 0x00000080}, ++ {EPACR0 + EPACR_STRIDE * 4, 0}, ++ {EPACR0 + EPACR_STRIDE * 5, 0x00000040}, ++ {EPACR0 + EPACR_STRIDE * 6, 0}, ++ {EPACR0 + EPACR_STRIDE * 7, 0}, ++ {EPACR0 + EPACR_STRIDE * 8, 0}, ++ {EPACR0 + EPACR_STRIDE * 9, 0x0000001C}, ++ {EPACR0 + EPACR_STRIDE * 10, 0x00000020}, ++ {EPACR0 + EPACR_STRIDE * 11, 0}, ++ {EPACR0 + EPACR_STRIDE * 12, 0x00000003}, ++ {EPACR0 + EPACR_STRIDE * 13, 0x06000000}, ++ {EPACR0 + EPACR_STRIDE * 14, 0x04000000}, ++ {EPACR0 + EPACR_STRIDE * 15, 0x02000000}, ++ /* EPIMCR (Event Processor Input Mux Control Registers) */ ++ {EPIMCR0 + EPIMCR_STRIDE * 0, 0}, ++ {EPIMCR0 + EPIMCR_STRIDE * 1, 0}, ++ {EPIMCR0 + EPIMCR_STRIDE * 2, 0}, ++ {EPIMCR0 + EPIMCR_STRIDE * 3, 0}, ++ {EPIMCR0 + EPIMCR_STRIDE * 4, 0x44000000}, ++ {EPIMCR0 + EPIMCR_STRIDE * 5, 0x40000000}, ++ {EPIMCR0 + EPIMCR_STRIDE * 6, 0}, ++ {EPIMCR0 + EPIMCR_STRIDE * 7, 0}, ++ {EPIMCR0 + EPIMCR_STRIDE * 8, 0}, ++ {EPIMCR0 + EPIMCR_STRIDE * 9, 0}, ++ {EPIMCR0 + EPIMCR_STRIDE * 10, 0}, ++ {EPIMCR0 + EPIMCR_STRIDE * 11, 0}, ++ {EPIMCR0 + EPIMCR_STRIDE * 12, 0x44000000}, ++ {EPIMCR0 + EPIMCR_STRIDE * 13, 0}, ++ {EPIMCR0 + EPIMCR_STRIDE * 14, 0}, ++ {EPIMCR0 + EPIMCR_STRIDE * 15, 0}, ++ {EPIMCR0 + EPIMCR_STRIDE * 16, 0x6A000000}, ++ {EPIMCR0 + EPIMCR_STRIDE * 17, 0}, ++ {EPIMCR0 + EPIMCR_STRIDE * 18, 0}, ++ {EPIMCR0 + EPIMCR_STRIDE * 19, 0}, ++ {EPIMCR0 + EPIMCR_STRIDE * 20, 0x48000000}, ++ {EPIMCR0 + EPIMCR_STRIDE * 21, 0}, ++ {EPIMCR0 + EPIMCR_STRIDE * 22, 0x6C000000}, ++ {EPIMCR0 + EPIMCR_STRIDE * 23, 0}, ++ {EPIMCR0 + EPIMCR_STRIDE * 24, 0}, ++ {EPIMCR0 + EPIMCR_STRIDE * 25, 0}, ++ {EPIMCR0 + EPIMCR_STRIDE * 26, 0}, ++ {EPIMCR0 + EPIMCR_STRIDE * 27, 0}, ++ {EPIMCR0 + EPIMCR_STRIDE * 28, 0x76000000}, ++ {EPIMCR0 + EPIMCR_STRIDE * 29, 0}, ++ {EPIMCR0 + EPIMCR_STRIDE * 30, 0}, ++ {EPIMCR0 + EPIMCR_STRIDE * 31, 0x76000000}, ++ /* EPXTRIGCR (Event Processor Crosstrigger Control Register) */ ++ {EPXTRIGCR, 0x0000FFDF}, ++ /* end */ ++ {FSM_END_FLAG, 0}, ++}; ++ ++struct fsm_reg_vals npc_default_val[] = { ++ /* NPC triggered Memory-Mapped Access Registers */ ++ {NCR, 0x80000000}, ++ {MCCR1, 0}, ++ {MCSR1, 0}, ++ {MMAR1LO, 0}, ++ {MMAR1HI, 0}, ++ {MMDR1, 0}, ++ {MCSR2, 0}, ++ {MMAR2LO, 0}, ++ {MMAR2HI, 0}, ++ {MMDR2, 0}, ++ {MCSR3, 0x80000000}, ++ {MMAR3LO, 0x000E2130}, ++ {MMAR3HI, 0x00030000}, ++ {MMDR3, 0x00020000}, ++ /* end */ ++ {FSM_END_FLAG, 0}, ++}; ++ ++/** ++ * fsl_fsm_setup - Configure EPU's FSM registers ++ * @base: the base address of registers ++ * @val: Pointer to address-value pairs for FSM registers ++ */ ++void fsl_fsm_setup(void __iomem *base, struct fsm_reg_vals *val) ++{ ++ struct fsm_reg_vals *data = val; ++ ++ WARN_ON(!base || !data); ++ while (data->offset != FSM_END_FLAG) { ++ iowrite32be(data->value, base + data->offset); ++ data++; ++ } ++} ++ ++void fsl_epu_setup_default(void __iomem *epu_base) ++{ ++ fsl_fsm_setup(epu_base, epu_default_val); ++} ++ ++void fsl_npc_setup_default(void __iomem *npc_base) ++{ ++ fsl_fsm_setup(npc_base, npc_default_val); ++} ++ ++void fsl_epu_clean_default(void __iomem *epu_base) ++{ ++ u32 offset; ++ ++ /* follow the exact sequence to clear the registers */ ++ /* Clear EPACRn */ ++ for (offset = EPACR0; offset <= EPACR15; offset += EPACR_STRIDE) ++ iowrite32be(0, epu_base + offset); ++ ++ /* Clear EPEVTCRn */ ++ for (offset = EPEVTCR0; offset <= EPEVTCR9; offset += EPEVTCR_STRIDE) ++ iowrite32be(0, epu_base + offset); ++ ++ /* Clear EPGCR */ ++ iowrite32be(0, epu_base + EPGCR); ++ ++ /* Clear EPSMCRn */ ++ for (offset = EPSMCR0; offset <= EPSMCR15; offset += EPSMCR_STRIDE) ++ iowrite32be(0, epu_base + offset); ++ ++ /* Clear EPCCRn */ ++ for (offset = EPCCR0; offset <= EPCCR31; offset += EPCCR_STRIDE) ++ iowrite32be(0, epu_base + offset); ++ ++ /* Clear EPCMPRn */ ++ for (offset = EPCMPR0; offset <= EPCMPR31; offset += EPCMPR_STRIDE) ++ iowrite32be(0, epu_base + offset); ++ ++ /* Clear EPCTRn */ ++ for (offset = EPCTR0; offset <= EPCTR31; offset += EPCTR_STRIDE) ++ iowrite32be(0, epu_base + offset); ++ ++ /* Clear EPIMCRn */ ++ for (offset = EPIMCR0; offset <= EPIMCR31; offset += EPIMCR_STRIDE) ++ iowrite32be(0, epu_base + offset); ++ ++ /* Clear EPXTRIGCRn */ ++ iowrite32be(0, epu_base + EPXTRIGCR); ++ ++ /* Clear EPECRn */ ++ for (offset = EPECR0; offset <= EPECR15; offset += EPECR_STRIDE) ++ iowrite32be(0, epu_base + offset); ++} +--- /dev/null ++++ b/drivers/soc/fsl/sleep_fsm.h +@@ -0,0 +1,130 @@ ++/* ++ * deep sleep FSM (finite-state machine) configuration ++ * ++ * Copyright 2018 NXP ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#ifndef _FSL_SLEEP_FSM_H ++#define _FSL_SLEEP_FSM_H ++ ++#define FSL_STRIDE_4B 4 ++#define FSL_STRIDE_8B 8 ++ ++/* End flag */ ++#define FSM_END_FLAG 0xFFFFFFFFUL ++ ++/* Block offsets */ ++#define RCPM_BLOCK_OFFSET 0x00022000 ++#define EPU_BLOCK_OFFSET 0x00000000 ++#define NPC_BLOCK_OFFSET 0x00001000 ++ ++/* EPGCR (Event Processor Global Control Register) */ ++#define EPGCR 0x000 ++ ++/* EPEVTCR0-9 (Event Processor EVT Pin Control Registers) */ ++#define EPEVTCR0 0x050 ++#define EPEVTCR9 0x074 ++#define EPEVTCR_STRIDE FSL_STRIDE_4B ++ ++/* EPXTRIGCR (Event Processor Crosstrigger Control Register) */ ++#define EPXTRIGCR 0x090 ++ ++/* EPIMCR0-31 (Event Processor Input Mux Control Registers) */ ++#define EPIMCR0 0x100 ++#define EPIMCR31 0x17C ++#define EPIMCR_STRIDE FSL_STRIDE_4B ++ ++/* EPSMCR0-15 (Event Processor SCU Mux Control Registers) */ ++#define EPSMCR0 0x200 ++#define EPSMCR15 0x278 ++#define EPSMCR_STRIDE FSL_STRIDE_8B ++ ++/* EPECR0-15 (Event Processor Event Control Registers) */ ++#define EPECR0 0x300 ++#define EPECR15 0x33C ++#define EPECR_STRIDE FSL_STRIDE_4B ++ ++/* EPACR0-15 (Event Processor Action Control Registers) */ ++#define EPACR0 0x400 ++#define EPACR15 0x43C ++#define EPACR_STRIDE FSL_STRIDE_4B ++ ++/* EPCCRi0-15 (Event Processor Counter Control Registers) */ ++#define EPCCR0 0x800 ++#define EPCCR15 0x83C ++#define EPCCR31 0x87C ++#define EPCCR_STRIDE FSL_STRIDE_4B ++ ++/* EPCMPR0-15 (Event Processor Counter Compare Registers) */ ++#define EPCMPR0 0x900 ++#define EPCMPR15 0x93C ++#define EPCMPR31 0x97C ++#define EPCMPR_STRIDE FSL_STRIDE_4B ++ ++/* EPCTR0-31 (Event Processor Counter Register) */ ++#define EPCTR0 0xA00 ++#define EPCTR31 0xA7C ++#define EPCTR_STRIDE FSL_STRIDE_4B ++ ++/* NPC triggered Memory-Mapped Access Registers */ ++#define NCR 0x000 ++#define MCCR1 0x0CC ++#define MCSR1 0x0D0 ++#define MMAR1LO 0x0D4 ++#define MMAR1HI 0x0D8 ++#define MMDR1 0x0DC ++#define MCSR2 0x0E0 ++#define MMAR2LO 0x0E4 ++#define MMAR2HI 0x0E8 ++#define MMDR2 0x0EC ++#define MCSR3 0x0F0 ++#define MMAR3LO 0x0F4 ++#define MMAR3HI 0x0F8 ++#define MMDR3 0x0FC ++ ++/* RCPM Core State Action Control Register 0 */ ++#define CSTTACR0 0xB00 ++ ++/* RCPM Core Group 1 Configuration Register 0 */ ++#define CG1CR0 0x31C ++ ++struct fsm_reg_vals { ++ u32 offset; ++ u32 value; ++}; ++ ++void fsl_fsm_setup(void __iomem *base, struct fsm_reg_vals *val); ++void fsl_epu_setup_default(void __iomem *epu_base); ++void fsl_npc_setup_default(void __iomem *npc_base); ++void fsl_epu_clean_default(void __iomem *epu_base); ++ ++#endif /* _FSL_SLEEP_FSM_H */ diff --git a/target/linux/layerscape/patches-4.9/804-crypto-support-layerscape.patch b/target/linux/layerscape/patches-4.9/804-crypto-support-layerscape.patch index a143ad566b..56a3dc01c4 100644 --- a/target/linux/layerscape/patches-4.9/804-crypto-support-layerscape.patch +++ b/target/linux/layerscape/patches-4.9/804-crypto-support-layerscape.patch @@ -1,7 +1,7 @@ -From a3310d64d7cb1ba0f9279e77d21f13a75fa66ab5 Mon Sep 17 00:00:00 2001 +From 2a0aa9bd187f6f5693982a8f79665585af772237 Mon Sep 17 00:00:00 2001 From: Yangbo Lu <yangbo.lu@nxp.com> -Date: Wed, 17 Jan 2018 15:29:23 +0800 -Subject: [PATCH 16/30] crypto: support layerscape +Date: Thu, 5 Jul 2018 17:29:41 +0800 +Subject: [PATCH 16/32] crypto: support layerscape MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -27,66 +27,67 @@ Signed-off-by: Arvind Yadav <arvind.yadav.cs@gmail.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Laura Abbott <labbott@redhat.com> Signed-off-by: Horia Geantă <horia.geanta@nxp.com> -Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +Singed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- - crypto/Kconfig | 30 + - crypto/Makefile | 4 + - crypto/acompress.c | 169 + - crypto/algboss.c | 12 +- - crypto/crypto_user.c | 19 + - crypto/scompress.c | 356 ++ - crypto/tcrypt.c | 17 +- - crypto/testmgr.c | 1708 +++--- - crypto/testmgr.h | 1125 ++-- - crypto/tls.c | 607 +++ - drivers/crypto/caam/Kconfig | 77 +- - drivers/crypto/caam/Makefile | 16 +- - drivers/crypto/caam/caamalg.c | 2171 ++------ - drivers/crypto/caam/caamalg_desc.c | 1961 +++++++ - drivers/crypto/caam/caamalg_desc.h | 127 + - drivers/crypto/caam/caamalg_qi.c | 2929 ++++++++++ - drivers/crypto/caam/caamalg_qi2.c | 5920 +++++++++++++++++++++ - drivers/crypto/caam/caamalg_qi2.h | 281 + - drivers/crypto/caam/caamhash.c | 550 +- - drivers/crypto/caam/caamhash_desc.c | 108 + - drivers/crypto/caam/caamhash_desc.h | 49 + - drivers/crypto/caam/caampkc.c | 471 +- - drivers/crypto/caam/caampkc.h | 58 + - drivers/crypto/caam/caamrng.c | 16 +- - drivers/crypto/caam/compat.h | 1 + - drivers/crypto/caam/ctrl.c | 358 +- - drivers/crypto/caam/ctrl.h | 2 + - drivers/crypto/caam/desc.h | 84 +- - drivers/crypto/caam/desc_constr.h | 180 +- - drivers/crypto/caam/dpseci.c | 859 +++ - drivers/crypto/caam/dpseci.h | 395 ++ - drivers/crypto/caam/dpseci_cmd.h | 261 + - drivers/crypto/caam/error.c | 127 +- - drivers/crypto/caam/error.h | 10 +- - drivers/crypto/caam/intern.h | 31 +- - drivers/crypto/caam/jr.c | 72 +- - drivers/crypto/caam/jr.h | 2 + - drivers/crypto/caam/key_gen.c | 32 +- - drivers/crypto/caam/key_gen.h | 36 +- - drivers/crypto/caam/pdb.h | 62 + - drivers/crypto/caam/pkc_desc.c | 36 + - drivers/crypto/caam/qi.c | 797 +++ - drivers/crypto/caam/qi.h | 204 + - drivers/crypto/caam/regs.h | 63 +- - drivers/crypto/caam/sg_sw_qm.h | 126 + - drivers/crypto/caam/sg_sw_qm2.h | 81 + - drivers/crypto/caam/sg_sw_sec4.h | 60 +- - drivers/net/wireless/rsi/rsi_91x_usb.c | 2 +- - drivers/staging/wilc1000/linux_wlan.c | 2 +- - drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 2 +- - include/crypto/acompress.h | 269 + - include/crypto/internal/acompress.h | 81 + - include/crypto/internal/scompress.h | 136 + - include/linux/crypto.h | 3 + - include/uapi/linux/cryptouser.h | 5 + - scripts/spelling.txt | 3 + - sound/soc/amd/acp-pcm-dma.c | 2 +- - 57 files changed, 19177 insertions(+), 3988 deletions(-) + crypto/Kconfig | 30 + + crypto/Makefile | 4 + + crypto/acompress.c | 169 + + crypto/algboss.c | 12 +- + crypto/crypto_user.c | 19 + + crypto/scompress.c | 356 + + crypto/tcrypt.c | 17 +- + crypto/testmgr.c | 1708 ++--- + crypto/testmgr.h | 1125 ++-- + crypto/tls.c | 607 ++ + drivers/crypto/caam/Kconfig | 77 +- + drivers/crypto/caam/Makefile | 16 +- + drivers/crypto/caam/caamalg.c | 2185 ++---- + drivers/crypto/caam/caamalg_desc.c | 1961 ++++++ + drivers/crypto/caam/caamalg_desc.h | 127 + + drivers/crypto/caam/caamalg_qi.c | 3321 +++++++++ + drivers/crypto/caam/caamalg_qi2.c | 5938 +++++++++++++++++ + drivers/crypto/caam/caamalg_qi2.h | 283 + + drivers/crypto/caam/caamhash.c | 555 +- + drivers/crypto/caam/caamhash_desc.c | 108 + + drivers/crypto/caam/caamhash_desc.h | 49 + + drivers/crypto/caam/caampkc.c | 471 +- + drivers/crypto/caam/caampkc.h | 58 + + drivers/crypto/caam/caamrng.c | 16 +- + drivers/crypto/caam/compat.h | 1 + + drivers/crypto/caam/ctrl.c | 358 +- + drivers/crypto/caam/ctrl.h | 2 + + drivers/crypto/caam/desc.h | 84 +- + drivers/crypto/caam/desc_constr.h | 180 +- + drivers/crypto/caam/dpseci.c | 858 +++ + drivers/crypto/caam/dpseci.h | 395 ++ + drivers/crypto/caam/dpseci_cmd.h | 261 + + drivers/crypto/caam/error.c | 127 +- + drivers/crypto/caam/error.h | 10 +- + drivers/crypto/caam/intern.h | 31 +- + drivers/crypto/caam/jr.c | 72 +- + drivers/crypto/caam/jr.h | 2 + + drivers/crypto/caam/key_gen.c | 32 +- + drivers/crypto/caam/key_gen.h | 36 +- + drivers/crypto/caam/pdb.h | 62 + + drivers/crypto/caam/pkc_desc.c | 36 + + drivers/crypto/caam/qi.c | 804 +++ + drivers/crypto/caam/qi.h | 204 + + drivers/crypto/caam/regs.h | 63 +- + drivers/crypto/caam/sg_sw_qm.h | 126 + + drivers/crypto/caam/sg_sw_qm2.h | 81 + + drivers/crypto/caam/sg_sw_sec4.h | 60 +- + drivers/crypto/talitos.c | 8 + + drivers/net/wireless/rsi/rsi_91x_usb.c | 2 +- + drivers/staging/wilc1000/linux_wlan.c | 2 +- + .../staging/wilc1000/wilc_wfi_cfgoperations.c | 2 +- + include/crypto/acompress.h | 269 + + include/crypto/internal/acompress.h | 81 + + include/crypto/internal/scompress.h | 136 + + include/linux/crypto.h | 3 + + include/uapi/linux/cryptouser.h | 5 + + scripts/spelling.txt | 3 + + sound/soc/amd/acp-pcm-dma.c | 2 +- + 58 files changed, 19620 insertions(+), 3990 deletions(-) create mode 100644 crypto/acompress.c create mode 100644 crypto/scompress.c create mode 100644 crypto/tls.c @@ -7200,7 +7201,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> bool rfc3686; bool geniv; }; -@@ -163,302 +96,70 @@ struct caam_aead_alg { +@@ -163,302 +96,71 @@ struct caam_aead_alg { bool registered; }; @@ -7270,6 +7271,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - unsigned int enckeylen; - unsigned int split_key_len; - unsigned int split_key_pad_len; ++ enum dma_data_direction dir; + struct device *jrdev; + struct alginfo adata; + struct alginfo cdata; @@ -7432,7 +7434,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + cnstr_shdsc_aead_null_encap(desc, &ctx->adata, ctx->authsize, + ctrlpriv->era); + dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma, -+ desc_bytes(desc), DMA_TO_DEVICE); ++ desc_bytes(desc), ctx->dir); /* * Job Descriptor and Shared Descriptors @@ -7529,11 +7531,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + cnstr_shdsc_aead_null_decap(desc, &ctx->adata, ctx->authsize, + ctrlpriv->era); + dma_sync_single_for_device(jrdev, ctx->sh_desc_dec_dma, -+ desc_bytes(desc), DMA_TO_DEVICE); ++ desc_bytes(desc), ctx->dir); return 0; } -@@ -470,11 +171,12 @@ static int aead_set_sh_desc(struct crypt +@@ -470,11 +172,12 @@ static int aead_set_sh_desc(struct crypt unsigned int ivsize = crypto_aead_ivsize(aead); struct caam_ctx *ctx = crypto_aead_ctx(aead); struct device *jrdev = ctx->jrdev; @@ -7550,7 +7552,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> OP_ALG_AAI_CTR_MOD128); const bool is_rfc3686 = alg->caam.rfc3686; -@@ -482,7 +184,7 @@ static int aead_set_sh_desc(struct crypt +@@ -482,7 +185,7 @@ static int aead_set_sh_desc(struct crypt return 0; /* NULL encryption / decryption */ @@ -7559,7 +7561,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> return aead_null_set_sh_desc(aead); /* -@@ -497,8 +199,14 @@ static int aead_set_sh_desc(struct crypt +@@ -497,8 +200,14 @@ static int aead_set_sh_desc(struct crypt * RFC3686 specific: * CONTEXT1[255:128] = {NONCE, IV, COUNTER} */ @@ -7575,7 +7577,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> if (alg->caam.geniv) goto skip_enc; -@@ -507,146 +215,64 @@ static int aead_set_sh_desc(struct crypt +@@ -507,146 +216,64 @@ static int aead_set_sh_desc(struct crypt * Job Descriptor and Shared Descriptors * must all fit into the 64-word Descriptor h/w Buffer */ @@ -7660,7 +7662,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + ctx->authsize, is_rfc3686, nonce, ctx1_iv_off, + false, ctrlpriv->era); + dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma, -+ desc_bytes(desc), DMA_TO_DEVICE); ++ desc_bytes(desc), ctx->dir); skip_enc: /* @@ -7760,11 +7762,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + ctx->authsize, alg->caam.geniv, is_rfc3686, + nonce, ctx1_iv_off, false, ctrlpriv->era); + dma_sync_single_for_device(jrdev, ctx->sh_desc_dec_dma, -+ desc_bytes(desc), DMA_TO_DEVICE); ++ desc_bytes(desc), ctx->dir); if (!alg->caam.geniv) goto skip_givenc; -@@ -655,107 +281,32 @@ skip_enc: +@@ -655,107 +282,32 @@ skip_enc: * Job Descriptor and Shared Descriptors * must all fit into the 64-word Descriptor h/w Buffer */ @@ -7890,11 +7892,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + ctx->authsize, is_rfc3686, nonce, + ctx1_iv_off, false, ctrlpriv->era); + dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma, -+ desc_bytes(desc), DMA_TO_DEVICE); ++ desc_bytes(desc), ctx->dir); skip_givenc: return 0; -@@ -776,12 +327,12 @@ static int gcm_set_sh_desc(struct crypto +@@ -776,12 +328,12 @@ static int gcm_set_sh_desc(struct crypto { struct caam_ctx *ctx = crypto_aead_ctx(aead); struct device *jrdev = ctx->jrdev; @@ -7911,7 +7913,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> return 0; /* -@@ -789,175 +340,35 @@ static int gcm_set_sh_desc(struct crypto +@@ -789,175 +341,35 @@ static int gcm_set_sh_desc(struct crypto * Job Descriptor and Shared Descriptor * must fit into the 64-word Descriptor h/w Buffer */ @@ -8012,7 +8014,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> -#endif + cnstr_shdsc_gcm_encap(desc, &ctx->cdata, ivsize, ctx->authsize, false); + dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma, -+ desc_bytes(desc), DMA_TO_DEVICE); ++ desc_bytes(desc), ctx->dir); /* * Job Descriptor and Shared Descriptors @@ -8103,11 +8105,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> -#endif + cnstr_shdsc_gcm_decap(desc, &ctx->cdata, ivsize, ctx->authsize, false); + dma_sync_single_for_device(jrdev, ctx->sh_desc_dec_dma, -+ desc_bytes(desc), DMA_TO_DEVICE); ++ desc_bytes(desc), ctx->dir); return 0; } -@@ -976,11 +387,12 @@ static int rfc4106_set_sh_desc(struct cr +@@ -976,11 +388,12 @@ static int rfc4106_set_sh_desc(struct cr { struct caam_ctx *ctx = crypto_aead_ctx(aead); struct device *jrdev = ctx->jrdev; @@ -8123,7 +8125,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> return 0; /* -@@ -988,148 +400,37 @@ static int rfc4106_set_sh_desc(struct cr +@@ -988,148 +401,37 @@ static int rfc4106_set_sh_desc(struct cr * Job Descriptor and Shared Descriptor * must fit into the 64-word Descriptor h/w Buffer */ @@ -8205,7 +8207,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + cnstr_shdsc_rfc4106_encap(desc, &ctx->cdata, ivsize, ctx->authsize, + false); + dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma, -+ desc_bytes(desc), DMA_TO_DEVICE); ++ desc_bytes(desc), ctx->dir); /* * Job Descriptor and Shared Descriptors @@ -8290,11 +8292,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + cnstr_shdsc_rfc4106_decap(desc, &ctx->cdata, ivsize, ctx->authsize, + false); + dma_sync_single_for_device(jrdev, ctx->sh_desc_dec_dma, -+ desc_bytes(desc), DMA_TO_DEVICE); ++ desc_bytes(desc), ctx->dir); return 0; } -@@ -1149,12 +450,12 @@ static int rfc4543_set_sh_desc(struct cr +@@ -1149,12 +451,12 @@ static int rfc4543_set_sh_desc(struct cr { struct caam_ctx *ctx = crypto_aead_ctx(aead); struct device *jrdev = ctx->jrdev; @@ -8311,7 +8313,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> return 0; /* -@@ -1162,151 +463,37 @@ static int rfc4543_set_sh_desc(struct cr +@@ -1162,151 +464,37 @@ static int rfc4543_set_sh_desc(struct cr * Job Descriptor and Shared Descriptor * must fit into the 64-word Descriptor h/w Buffer */ @@ -8392,7 +8394,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + cnstr_shdsc_rfc4543_encap(desc, &ctx->cdata, ivsize, ctx->authsize, + false); + dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma, -+ desc_bytes(desc), DMA_TO_DEVICE); ++ desc_bytes(desc), ctx->dir); /* * Job Descriptor and Shared Descriptors @@ -8481,11 +8483,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + cnstr_shdsc_rfc4543_decap(desc, &ctx->cdata, ivsize, ctx->authsize, + false); + dma_sync_single_for_device(jrdev, ctx->sh_desc_dec_dma, -+ desc_bytes(desc), DMA_TO_DEVICE); ++ desc_bytes(desc), ctx->dir); return 0; } -@@ -1322,74 +509,67 @@ static int rfc4543_setauthsize(struct cr +@@ -1322,74 +510,67 @@ static int rfc4543_setauthsize(struct cr return 0; } @@ -8547,7 +8549,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + keys.enckeylen); + dma_sync_single_for_device(jrdev, ctx->key_dma, + ctx->adata.keylen_pad + -+ keys.enckeylen, DMA_TO_DEVICE); ++ keys.enckeylen, ctx->dir); + goto skip_split_key; + } + @@ -8569,7 +8571,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - } + memcpy(ctx->key + ctx->adata.keylen_pad, keys.enckey, keys.enckeylen); + dma_sync_single_for_device(jrdev, ctx->key_dma, ctx->adata.keylen_pad + -+ keys.enckeylen, DMA_TO_DEVICE); ++ keys.enckeylen, ctx->dir); #ifdef DEBUG print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, @@ -8592,7 +8594,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> badkey: crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); return -EINVAL; -@@ -1400,7 +580,6 @@ static int gcm_setkey(struct crypto_aead +@@ -1400,7 +581,6 @@ static int gcm_setkey(struct crypto_aead { struct caam_ctx *ctx = crypto_aead_ctx(aead); struct device *jrdev = ctx->jrdev; @@ -8600,7 +8602,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> #ifdef DEBUG print_hex_dump(KERN_ERR, "key in @"__stringify(__LINE__)": ", -@@ -1408,21 +587,10 @@ static int gcm_setkey(struct crypto_aead +@@ -1408,21 +588,10 @@ static int gcm_setkey(struct crypto_aead #endif memcpy(ctx->key, key, keylen); @@ -8611,7 +8613,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - return -ENOMEM; - } - ctx->enckeylen = keylen; -+ dma_sync_single_for_device(jrdev, ctx->key_dma, keylen, DMA_TO_DEVICE); ++ dma_sync_single_for_device(jrdev, ctx->key_dma, keylen, ctx->dir); + ctx->cdata.keylen = keylen; - ret = gcm_set_sh_desc(aead); @@ -8625,7 +8627,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> } static int rfc4106_setkey(struct crypto_aead *aead, -@@ -1430,7 +598,6 @@ static int rfc4106_setkey(struct crypto_ +@@ -1430,7 +599,6 @@ static int rfc4106_setkey(struct crypto_ { struct caam_ctx *ctx = crypto_aead_ctx(aead); struct device *jrdev = ctx->jrdev; @@ -8633,7 +8635,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> if (keylen < 4) return -EINVAL; -@@ -1446,22 +613,10 @@ static int rfc4106_setkey(struct crypto_ +@@ -1446,22 +614,10 @@ static int rfc4106_setkey(struct crypto_ * The last four bytes of the key material are used as the salt value * in the nonce. Update the AES key length. */ @@ -8655,12 +8657,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - return ret; + ctx->cdata.keylen = keylen - 4; + dma_sync_single_for_device(jrdev, ctx->key_dma, ctx->cdata.keylen, -+ DMA_TO_DEVICE); ++ ctx->dir); + return rfc4106_set_sh_desc(aead); } static int rfc4543_setkey(struct crypto_aead *aead, -@@ -1469,7 +624,6 @@ static int rfc4543_setkey(struct crypto_ +@@ -1469,7 +625,6 @@ static int rfc4543_setkey(struct crypto_ { struct caam_ctx *ctx = crypto_aead_ctx(aead); struct device *jrdev = ctx->jrdev; @@ -8668,7 +8670,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> if (keylen < 4) return -EINVAL; -@@ -1485,43 +639,28 @@ static int rfc4543_setkey(struct crypto_ +@@ -1485,43 +640,28 @@ static int rfc4543_setkey(struct crypto_ * The last four bytes of the key material are used as the salt value * in the nonce. Update the AES key length. */ @@ -8690,7 +8692,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - return ret; + ctx->cdata.keylen = keylen - 4; + dma_sync_single_for_device(jrdev, ctx->key_dma, ctx->cdata.keylen, -+ DMA_TO_DEVICE); ++ ctx->dir); + return rfc4543_set_sh_desc(aead); } @@ -8719,7 +8721,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> #ifdef DEBUG print_hex_dump(KERN_ERR, "key in @"__stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); -@@ -1544,215 +683,33 @@ static int ablkcipher_setkey(struct cryp +@@ -1544,215 +684,33 @@ static int ablkcipher_setkey(struct cryp keylen -= CTR_RFC3686_NONCE_SIZE; } @@ -8766,11 +8768,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - /* Load iv */ - append_seq_load(desc, crt->ivsize, LDST_SRCDST_BYTE_CONTEXT | - LDST_CLASS_1_CCB | (ctx1_iv_off << LDST_OFFSET_SHIFT)); -+ cnstr_shdsc_ablkcipher_encap(desc, &ctx->cdata, ivsize, is_rfc3686, -+ ctx1_iv_off); -+ dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma, -+ desc_bytes(desc), DMA_TO_DEVICE); - +- - /* Load counter into CONTEXT1 reg */ - if (is_rfc3686) - append_load_imm_be32(desc, 1, LDST_IMM | LDST_CLASS_1_CCB | @@ -8784,7 +8782,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - - /* Perform operation */ - ablkcipher_append_src_dst(desc); -- ++ cnstr_shdsc_ablkcipher_encap(desc, &ctx->cdata, ivsize, is_rfc3686, ++ ctx1_iv_off); ++ dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma, ++ desc_bytes(desc), ctx->dir); + - ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc, - desc_bytes(desc), - DMA_TO_DEVICE); @@ -8803,7 +8805,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + cnstr_shdsc_ablkcipher_decap(desc, &ctx->cdata, ivsize, is_rfc3686, + ctx1_iv_off); + dma_sync_single_for_device(jrdev, ctx->sh_desc_dec_dma, -+ desc_bytes(desc), DMA_TO_DEVICE); ++ desc_bytes(desc), ctx->dir); - init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX); - /* Skip if already shared */ @@ -8870,7 +8872,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + cnstr_shdsc_ablkcipher_givencap(desc, &ctx->cdata, ivsize, is_rfc3686, + ctx1_iv_off); + dma_sync_single_for_device(jrdev, ctx->sh_desc_givenc_dma, -+ desc_bytes(desc), DMA_TO_DEVICE); ++ desc_bytes(desc), ctx->dir); - init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX); - /* Skip if already shared */ @@ -8952,7 +8954,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> } static int xts_ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher, -@@ -1760,8 +717,7 @@ static int xts_ablkcipher_setkey(struct +@@ -1760,8 +718,7 @@ static int xts_ablkcipher_setkey(struct { struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher); struct device *jrdev = ctx->jrdev; @@ -8962,7 +8964,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> if (keylen != 2 * AES_MIN_KEY_SIZE && keylen != 2 * AES_MAX_KEY_SIZE) { crypto_ablkcipher_set_flags(ablkcipher, -@@ -1771,126 +727,38 @@ static int xts_ablkcipher_setkey(struct +@@ -1771,126 +728,38 @@ static int xts_ablkcipher_setkey(struct } memcpy(ctx->key, key, keylen); @@ -9024,7 +9026,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> -#endif + cnstr_shdsc_xts_ablkcipher_encap(desc, &ctx->cdata); + dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma, -+ desc_bytes(desc), DMA_TO_DEVICE); ++ desc_bytes(desc), ctx->dir); /* xts_ablkcipher_decrypt shared descriptor */ desc = ctx->sh_desc_dec; @@ -9075,7 +9077,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> -#endif + cnstr_shdsc_xts_ablkcipher_decap(desc, &ctx->cdata); + dma_sync_single_for_device(jrdev, ctx->sh_desc_dec_dma, -+ desc_bytes(desc), DMA_TO_DEVICE); ++ desc_bytes(desc), ctx->dir); return 0; } @@ -9102,7 +9104,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> int sec4_sg_bytes; dma_addr_t sec4_sg_dma; struct sec4_sg_entry *sec4_sg; -@@ -1899,12 +767,12 @@ struct aead_edesc { +@@ -1899,12 +768,12 @@ struct aead_edesc { /* * ablkcipher_edesc - s/w-extended ablkcipher descriptor @@ -9118,7 +9120,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> * @hw_desc: the h/w job descriptor followed by any referenced link tables */ struct ablkcipher_edesc { -@@ -1924,10 +792,11 @@ static void caam_unmap(struct device *de +@@ -1924,10 +793,11 @@ static void caam_unmap(struct device *de int sec4_sg_bytes) { if (dst != src) { @@ -9133,7 +9135,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> } if (iv_dma) -@@ -2021,8 +890,7 @@ static void ablkcipher_encrypt_done(stru +@@ -2021,8 +891,7 @@ static void ablkcipher_encrypt_done(stru dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); #endif @@ -9143,7 +9145,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> if (err) caam_jr_strstatus(jrdev, err); -@@ -2031,10 +899,10 @@ static void ablkcipher_encrypt_done(stru +@@ -2031,10 +900,10 @@ static void ablkcipher_encrypt_done(stru print_hex_dump(KERN_ERR, "dstiv @"__stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, req->info, edesc->src_nents > 1 ? 100 : ivsize, 1); @@ -9157,7 +9159,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> ablkcipher_unmap(jrdev, edesc, req); -@@ -2062,8 +930,7 @@ static void ablkcipher_decrypt_done(stru +@@ -2062,8 +931,7 @@ static void ablkcipher_decrypt_done(stru dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); #endif @@ -9167,7 +9169,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> if (err) caam_jr_strstatus(jrdev, err); -@@ -2071,10 +938,10 @@ static void ablkcipher_decrypt_done(stru +@@ -2071,10 +939,10 @@ static void ablkcipher_decrypt_done(stru print_hex_dump(KERN_ERR, "dstiv @"__stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, req->info, ivsize, 1); @@ -9181,7 +9183,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> ablkcipher_unmap(jrdev, edesc, req); -@@ -2114,7 +981,7 @@ static void init_aead_job(struct aead_re +@@ -2114,7 +982,7 @@ static void init_aead_job(struct aead_re init_job_desc_shared(desc, ptr, len, HDR_SHARE_DEFER | HDR_REVERSE); if (all_contig) { @@ -9190,7 +9192,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> in_options = 0; } else { src_dma = edesc->sec4_sg_dma; -@@ -2129,7 +996,7 @@ static void init_aead_job(struct aead_re +@@ -2129,7 +997,7 @@ static void init_aead_job(struct aead_re out_options = in_options; if (unlikely(req->src != req->dst)) { @@ -9199,7 +9201,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> dst_dma = sg_dma_address(req->dst); } else { dst_dma = edesc->sec4_sg_dma + -@@ -2147,9 +1014,6 @@ static void init_aead_job(struct aead_re +@@ -2147,9 +1015,6 @@ static void init_aead_job(struct aead_re append_seq_out_ptr(desc, dst_dma, req->assoclen + req->cryptlen - authsize, out_options); @@ -9209,7 +9211,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> } static void init_gcm_job(struct aead_request *req, -@@ -2164,6 +1028,7 @@ static void init_gcm_job(struct aead_req +@@ -2164,6 +1029,7 @@ static void init_gcm_job(struct aead_req unsigned int last; init_aead_job(req, edesc, all_contig, encrypt); @@ -9217,7 +9219,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> /* BUG This should not be specific to generic GCM. */ last = 0; -@@ -2175,7 +1040,7 @@ static void init_gcm_job(struct aead_req +@@ -2175,7 +1041,7 @@ static void init_gcm_job(struct aead_req FIFOLD_TYPE_IV | FIFOLD_TYPE_FLUSH1 | 12 | last); /* Append Salt */ if (!generic_gcm) @@ -9226,7 +9228,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> /* Append IV */ append_data(desc, req->iv, ivsize); /* End of blank commands */ -@@ -2190,7 +1055,8 @@ static void init_authenc_job(struct aead +@@ -2190,7 +1056,8 @@ static void init_authenc_job(struct aead struct caam_aead_alg, aead); unsigned int ivsize = crypto_aead_ivsize(aead); struct caam_ctx *ctx = crypto_aead_ctx(aead); @@ -9236,7 +9238,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> OP_ALG_AAI_CTR_MOD128); const bool is_rfc3686 = alg->caam.rfc3686; u32 *desc = edesc->hw_desc; -@@ -2213,6 +1079,15 @@ static void init_authenc_job(struct aead +@@ -2213,6 +1080,15 @@ static void init_authenc_job(struct aead init_aead_job(req, edesc, all_contig, encrypt); @@ -9252,7 +9254,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> if (ivsize && ((is_rfc3686 && encrypt) || !alg->caam.geniv)) append_load_as_imm(desc, req->iv, ivsize, LDST_CLASS_1_CCB | -@@ -2236,16 +1111,15 @@ static void init_ablkcipher_job(u32 *sh_ +@@ -2236,16 +1112,15 @@ static void init_ablkcipher_job(u32 *sh_ int len, sec4_sg_index = 0; #ifdef DEBUG @@ -9274,7 +9276,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> len = desc_len(sh_desc); init_job_desc_shared(desc, ptr, len, HDR_SHARE_DEFER | HDR_REVERSE); -@@ -2261,7 +1135,7 @@ static void init_ablkcipher_job(u32 *sh_ +@@ -2261,7 +1136,7 @@ static void init_ablkcipher_job(u32 *sh_ append_seq_in_ptr(desc, src_dma, req->nbytes + ivsize, in_options); if (likely(req->src == req->dst)) { @@ -9283,7 +9285,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> dst_dma = sg_dma_address(req->src); } else { dst_dma = edesc->sec4_sg_dma + -@@ -2269,7 +1143,7 @@ static void init_ablkcipher_job(u32 *sh_ +@@ -2269,7 +1144,7 @@ static void init_ablkcipher_job(u32 *sh_ out_options = LDST_SGF; } } else { @@ -9292,7 +9294,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> dst_dma = sg_dma_address(req->dst); } else { dst_dma = edesc->sec4_sg_dma + -@@ -2296,20 +1170,18 @@ static void init_ablkcipher_giv_job(u32 +@@ -2296,20 +1171,18 @@ static void init_ablkcipher_giv_job(u32 int len, sec4_sg_index = 0; #ifdef DEBUG @@ -9317,7 +9319,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> src_dma = sg_dma_address(req->src); in_options = 0; } else { -@@ -2340,87 +1212,100 @@ static struct aead_edesc *aead_edesc_all +@@ -2340,87 +1213,100 @@ static struct aead_edesc *aead_edesc_all struct crypto_aead *aead = crypto_aead_reqtfm(req); struct caam_ctx *ctx = crypto_aead_ctx(aead); struct device *jrdev = ctx->jrdev; @@ -9473,7 +9475,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> edesc->sec4_sg + sec4_sg_index, 0); } -@@ -2573,13 +1458,9 @@ static int aead_decrypt(struct aead_requ +@@ -2573,13 +1459,9 @@ static int aead_decrypt(struct aead_requ u32 *desc; int ret = 0; @@ -9490,7 +9492,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> /* allocate extended descriptor */ edesc = aead_edesc_alloc(req, AUTHENC_DESC_JOB_IO_LEN, -@@ -2619,51 +1500,80 @@ static struct ablkcipher_edesc *ablkciph +@@ -2619,51 +1501,80 @@ static struct ablkcipher_edesc *ablkciph struct device *jrdev = ctx->jrdev; gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? GFP_KERNEL : GFP_ATOMIC; @@ -9594,7 +9596,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> return ERR_PTR(-ENOMEM); } -@@ -2673,23 +1583,24 @@ static struct ablkcipher_edesc *ablkciph +@@ -2673,23 +1584,24 @@ static struct ablkcipher_edesc *ablkciph edesc->sec4_sg = (void *)edesc + sizeof(struct ablkcipher_edesc) + desc_bytes; @@ -9626,7 +9628,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> return ERR_PTR(-ENOMEM); } -@@ -2701,7 +1612,7 @@ static struct ablkcipher_edesc *ablkciph +@@ -2701,7 +1613,7 @@ static struct ablkcipher_edesc *ablkciph sec4_sg_bytes, 1); #endif @@ -9635,7 +9637,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> return edesc; } -@@ -2792,30 +1703,54 @@ static struct ablkcipher_edesc *ablkciph +@@ -2792,30 +1704,54 @@ static struct ablkcipher_edesc *ablkciph struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher); struct device *jrdev = ctx->jrdev; @@ -9706,7 +9708,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> } /* -@@ -2825,21 +1760,29 @@ static struct ablkcipher_edesc *ablkciph +@@ -2825,21 +1761,29 @@ static struct ablkcipher_edesc *ablkciph iv_dma = dma_map_single(jrdev, greq->giv, ivsize, DMA_TO_DEVICE); if (dma_mapping_error(jrdev, iv_dma)) { dev_err(jrdev, "unable to map IV\n"); @@ -9742,7 +9744,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> return ERR_PTR(-ENOMEM); } -@@ -2849,24 +1792,24 @@ static struct ablkcipher_edesc *ablkciph +@@ -2849,24 +1793,24 @@ static struct ablkcipher_edesc *ablkciph edesc->sec4_sg = (void *)edesc + sizeof(struct ablkcipher_edesc) + desc_bytes; @@ -9777,7 +9779,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> return ERR_PTR(-ENOMEM); } edesc->iv_dma = iv_dma; -@@ -2878,7 +1821,7 @@ static struct ablkcipher_edesc *ablkciph +@@ -2878,7 +1822,7 @@ static struct ablkcipher_edesc *ablkciph sec4_sg_bytes, 1); #endif @@ -9786,7 +9788,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> return edesc; } -@@ -2889,7 +1832,7 @@ static int ablkcipher_givencrypt(struct +@@ -2889,7 +1833,7 @@ static int ablkcipher_givencrypt(struct struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher); struct device *jrdev = ctx->jrdev; @@ -9795,7 +9797,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> u32 *desc; int ret = 0; -@@ -2933,7 +1876,6 @@ struct caam_alg_template { +@@ -2933,7 +1877,6 @@ struct caam_alg_template { } template_u; u32 class1_alg_type; u32 class2_alg_type; @@ -9803,7 +9805,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }; static struct caam_alg_template driver_algs[] = { -@@ -3118,7 +2060,6 @@ static struct caam_aead_alg driver_aeads +@@ -3118,7 +2061,6 @@ static struct caam_aead_alg driver_aeads .caam = { .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP, @@ -9811,7 +9813,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, }, { -@@ -3140,7 +2081,6 @@ static struct caam_aead_alg driver_aeads +@@ -3140,7 +2082,6 @@ static struct caam_aead_alg driver_aeads .caam = { .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP, @@ -9819,7 +9821,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, }, { -@@ -3162,7 +2102,6 @@ static struct caam_aead_alg driver_aeads +@@ -3162,7 +2103,6 @@ static struct caam_aead_alg driver_aeads .caam = { .class2_alg_type = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC_PRECOMP, @@ -9827,7 +9829,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, }, { -@@ -3184,7 +2123,6 @@ static struct caam_aead_alg driver_aeads +@@ -3184,7 +2124,6 @@ static struct caam_aead_alg driver_aeads .caam = { .class2_alg_type = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC_PRECOMP, @@ -9835,7 +9837,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, }, { -@@ -3206,7 +2144,6 @@ static struct caam_aead_alg driver_aeads +@@ -3206,7 +2145,6 @@ static struct caam_aead_alg driver_aeads .caam = { .class2_alg_type = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC_PRECOMP, @@ -9843,7 +9845,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, }, { -@@ -3228,7 +2165,6 @@ static struct caam_aead_alg driver_aeads +@@ -3228,7 +2166,6 @@ static struct caam_aead_alg driver_aeads .caam = { .class2_alg_type = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC_PRECOMP, @@ -9851,7 +9853,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, }, { -@@ -3250,7 +2186,6 @@ static struct caam_aead_alg driver_aeads +@@ -3250,7 +2187,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP, @@ -9859,7 +9861,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, }, { -@@ -3273,7 +2208,6 @@ static struct caam_aead_alg driver_aeads +@@ -3273,7 +2209,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP, @@ -9867,7 +9869,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .geniv = true, }, }, -@@ -3296,7 +2230,6 @@ static struct caam_aead_alg driver_aeads +@@ -3296,7 +2231,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP, @@ -9875,7 +9877,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, }, { -@@ -3319,7 +2252,6 @@ static struct caam_aead_alg driver_aeads +@@ -3319,7 +2253,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP, @@ -9883,7 +9885,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .geniv = true, }, }, -@@ -3342,7 +2274,6 @@ static struct caam_aead_alg driver_aeads +@@ -3342,7 +2275,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC_PRECOMP, @@ -9891,7 +9893,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, }, { -@@ -3365,7 +2296,6 @@ static struct caam_aead_alg driver_aeads +@@ -3365,7 +2297,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC_PRECOMP, @@ -9899,7 +9901,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .geniv = true, }, }, -@@ -3388,7 +2318,6 @@ static struct caam_aead_alg driver_aeads +@@ -3388,7 +2319,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC_PRECOMP, @@ -9907,7 +9909,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, }, { -@@ -3411,7 +2340,6 @@ static struct caam_aead_alg driver_aeads +@@ -3411,7 +2341,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC_PRECOMP, @@ -9915,7 +9917,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .geniv = true, }, }, -@@ -3434,7 +2362,6 @@ static struct caam_aead_alg driver_aeads +@@ -3434,7 +2363,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC_PRECOMP, @@ -9923,7 +9925,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, }, { -@@ -3457,7 +2384,6 @@ static struct caam_aead_alg driver_aeads +@@ -3457,7 +2385,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC_PRECOMP, @@ -9931,7 +9933,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .geniv = true, }, }, -@@ -3480,7 +2406,6 @@ static struct caam_aead_alg driver_aeads +@@ -3480,7 +2407,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC_PRECOMP, @@ -9939,7 +9941,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, }, { -@@ -3503,7 +2428,6 @@ static struct caam_aead_alg driver_aeads +@@ -3503,7 +2429,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC_PRECOMP, @@ -9947,7 +9949,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .geniv = true, }, }, -@@ -3526,7 +2450,6 @@ static struct caam_aead_alg driver_aeads +@@ -3526,7 +2451,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP, @@ -9955,7 +9957,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> } }, { -@@ -3549,7 +2472,6 @@ static struct caam_aead_alg driver_aeads +@@ -3549,7 +2473,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP, @@ -9963,7 +9965,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .geniv = true, } }, -@@ -3573,7 +2495,6 @@ static struct caam_aead_alg driver_aeads +@@ -3573,7 +2496,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP, @@ -9971,7 +9973,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, }, { -@@ -3597,7 +2518,6 @@ static struct caam_aead_alg driver_aeads +@@ -3597,7 +2519,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP, @@ -9979,7 +9981,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .geniv = true, }, }, -@@ -3621,7 +2541,6 @@ static struct caam_aead_alg driver_aeads +@@ -3621,7 +2542,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC_PRECOMP, @@ -9987,7 +9989,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, }, { -@@ -3645,7 +2564,6 @@ static struct caam_aead_alg driver_aeads +@@ -3645,7 +2565,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC_PRECOMP, @@ -9995,7 +9997,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .geniv = true, }, }, -@@ -3669,7 +2587,6 @@ static struct caam_aead_alg driver_aeads +@@ -3669,7 +2588,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10003,7 +10005,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, }, { -@@ -3693,7 +2610,6 @@ static struct caam_aead_alg driver_aeads +@@ -3693,7 +2611,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10011,7 +10013,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .geniv = true, }, }, -@@ -3717,7 +2633,6 @@ static struct caam_aead_alg driver_aeads +@@ -3717,7 +2634,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10019,7 +10021,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, }, { -@@ -3741,7 +2656,6 @@ static struct caam_aead_alg driver_aeads +@@ -3741,7 +2657,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10027,7 +10029,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .geniv = true, }, }, -@@ -3765,7 +2679,6 @@ static struct caam_aead_alg driver_aeads +@@ -3765,7 +2680,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10035,7 +10037,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, }, { -@@ -3789,7 +2702,6 @@ static struct caam_aead_alg driver_aeads +@@ -3789,7 +2703,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10043,7 +10045,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .geniv = true, }, }, -@@ -3812,7 +2724,6 @@ static struct caam_aead_alg driver_aeads +@@ -3812,7 +2725,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10051,7 +10053,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, }, { -@@ -3835,7 +2746,6 @@ static struct caam_aead_alg driver_aeads +@@ -3835,7 +2747,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10059,7 +10061,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .geniv = true, }, }, -@@ -3858,7 +2768,6 @@ static struct caam_aead_alg driver_aeads +@@ -3858,7 +2769,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10067,7 +10069,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, }, { -@@ -3881,7 +2790,6 @@ static struct caam_aead_alg driver_aeads +@@ -3881,7 +2791,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10075,7 +10077,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .geniv = true, }, }, -@@ -3904,7 +2812,6 @@ static struct caam_aead_alg driver_aeads +@@ -3904,7 +2813,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10083,7 +10085,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, }, { -@@ -3927,7 +2834,6 @@ static struct caam_aead_alg driver_aeads +@@ -3927,7 +2835,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10091,7 +10093,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .geniv = true, }, }, -@@ -3950,7 +2856,6 @@ static struct caam_aead_alg driver_aeads +@@ -3950,7 +2857,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10099,7 +10101,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, }, { -@@ -3973,7 +2878,6 @@ static struct caam_aead_alg driver_aeads +@@ -3973,7 +2879,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10107,7 +10109,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .geniv = true, }, }, -@@ -3996,7 +2900,6 @@ static struct caam_aead_alg driver_aeads +@@ -3996,7 +2901,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10115,7 +10117,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, }, { -@@ -4019,7 +2922,6 @@ static struct caam_aead_alg driver_aeads +@@ -4019,7 +2923,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10123,7 +10125,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .geniv = true, }, }, -@@ -4042,7 +2944,6 @@ static struct caam_aead_alg driver_aeads +@@ -4042,7 +2945,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10131,7 +10133,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, }, { -@@ -4065,7 +2966,6 @@ static struct caam_aead_alg driver_aeads +@@ -4065,7 +2967,6 @@ static struct caam_aead_alg driver_aeads .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10139,7 +10141,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .geniv = true, }, }, -@@ -4090,7 +2990,6 @@ static struct caam_aead_alg driver_aeads +@@ -4090,7 +2991,6 @@ static struct caam_aead_alg driver_aeads OP_ALG_AAI_CTR_MOD128, .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10147,7 +10149,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .rfc3686 = true, }, }, -@@ -4115,7 +3014,6 @@ static struct caam_aead_alg driver_aeads +@@ -4115,7 +3015,6 @@ static struct caam_aead_alg driver_aeads OP_ALG_AAI_CTR_MOD128, .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10155,7 +10157,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .rfc3686 = true, .geniv = true, }, -@@ -4141,7 +3039,6 @@ static struct caam_aead_alg driver_aeads +@@ -4141,7 +3040,6 @@ static struct caam_aead_alg driver_aeads OP_ALG_AAI_CTR_MOD128, .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10163,7 +10165,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .rfc3686 = true, }, }, -@@ -4166,7 +3063,6 @@ static struct caam_aead_alg driver_aeads +@@ -4166,7 +3064,6 @@ static struct caam_aead_alg driver_aeads OP_ALG_AAI_CTR_MOD128, .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10171,7 +10173,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .rfc3686 = true, .geniv = true, }, -@@ -4192,7 +3088,6 @@ static struct caam_aead_alg driver_aeads +@@ -4192,7 +3089,6 @@ static struct caam_aead_alg driver_aeads OP_ALG_AAI_CTR_MOD128, .class2_alg_type = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10179,7 +10181,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .rfc3686 = true, }, }, -@@ -4217,7 +3112,6 @@ static struct caam_aead_alg driver_aeads +@@ -4217,7 +3113,6 @@ static struct caam_aead_alg driver_aeads OP_ALG_AAI_CTR_MOD128, .class2_alg_type = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10187,7 +10189,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .rfc3686 = true, .geniv = true, }, -@@ -4243,7 +3137,6 @@ static struct caam_aead_alg driver_aeads +@@ -4243,7 +3138,6 @@ static struct caam_aead_alg driver_aeads OP_ALG_AAI_CTR_MOD128, .class2_alg_type = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10195,7 +10197,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .rfc3686 = true, }, }, -@@ -4268,7 +3161,6 @@ static struct caam_aead_alg driver_aeads +@@ -4268,7 +3162,6 @@ static struct caam_aead_alg driver_aeads OP_ALG_AAI_CTR_MOD128, .class2_alg_type = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10203,7 +10205,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .rfc3686 = true, .geniv = true, }, -@@ -4294,7 +3186,6 @@ static struct caam_aead_alg driver_aeads +@@ -4294,7 +3187,6 @@ static struct caam_aead_alg driver_aeads OP_ALG_AAI_CTR_MOD128, .class2_alg_type = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10211,7 +10213,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .rfc3686 = true, }, }, -@@ -4319,7 +3210,6 @@ static struct caam_aead_alg driver_aeads +@@ -4319,7 +3211,6 @@ static struct caam_aead_alg driver_aeads OP_ALG_AAI_CTR_MOD128, .class2_alg_type = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10219,7 +10221,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .rfc3686 = true, .geniv = true, }, -@@ -4345,7 +3235,6 @@ static struct caam_aead_alg driver_aeads +@@ -4345,7 +3236,6 @@ static struct caam_aead_alg driver_aeads OP_ALG_AAI_CTR_MOD128, .class2_alg_type = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10227,7 +10229,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .rfc3686 = true, }, }, -@@ -4370,7 +3259,6 @@ static struct caam_aead_alg driver_aeads +@@ -4370,7 +3260,6 @@ static struct caam_aead_alg driver_aeads OP_ALG_AAI_CTR_MOD128, .class2_alg_type = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC_PRECOMP, @@ -10235,11 +10237,16 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> .rfc3686 = true, .geniv = true, }, -@@ -4385,16 +3273,34 @@ struct caam_crypto_alg { +@@ -4383,18 +3272,44 @@ struct caam_crypto_alg { + struct caam_alg_entry caam; + }; - static int caam_init_common(struct caam_ctx *ctx, struct caam_alg_entry *caam) +-static int caam_init_common(struct caam_ctx *ctx, struct caam_alg_entry *caam) ++static int caam_init_common(struct caam_ctx *ctx, struct caam_alg_entry *caam, ++ bool uses_dkp) { + dma_addr_t dma_addr; ++ struct caam_drv_private *priv; + ctx->jrdev = caam_jr_alloc(); if (IS_ERR(ctx->jrdev)) { @@ -10247,10 +10254,16 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> return PTR_ERR(ctx->jrdev); } ++ priv = dev_get_drvdata(ctx->jrdev->parent); ++ if (priv->era >= 6 && uses_dkp) ++ ctx->dir = DMA_BIDIRECTIONAL; ++ else ++ ctx->dir = DMA_TO_DEVICE; ++ + dma_addr = dma_map_single_attrs(ctx->jrdev, ctx->sh_desc_enc, + offsetof(struct caam_ctx, + sh_desc_enc_dma), -+ DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); ++ ctx->dir, DMA_ATTR_SKIP_CPU_SYNC); + if (dma_mapping_error(ctx->jrdev, dma_addr)) { + dev_err(ctx->jrdev, "unable to map key, shared descriptors\n"); + caam_jr_free(ctx->jrdev); @@ -10273,7 +10286,23 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> return 0; } -@@ -4421,25 +3327,9 @@ static int caam_aead_init(struct crypto_ +@@ -4406,7 +3321,7 @@ static int caam_cra_init(struct crypto_t + container_of(alg, struct caam_crypto_alg, crypto_alg); + struct caam_ctx *ctx = crypto_tfm_ctx(tfm); + +- return caam_init_common(ctx, &caam_alg->caam); ++ return caam_init_common(ctx, &caam_alg->caam, false); + } + + static int caam_aead_init(struct crypto_aead *tfm) +@@ -4416,30 +3331,15 @@ static int caam_aead_init(struct crypto_ + container_of(alg, struct caam_aead_alg, aead); + struct caam_ctx *ctx = crypto_aead_ctx(tfm); + +- return caam_init_common(ctx, &caam_alg->caam); ++ return caam_init_common(ctx, &caam_alg->caam, ++ alg->setkey == aead_setkey); + } static void caam_exit_common(struct caam_ctx *ctx) { @@ -10298,11 +10327,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - + dma_unmap_single_attrs(ctx->jrdev, ctx->sh_desc_enc_dma, + offsetof(struct caam_ctx, sh_desc_enc_dma), -+ DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); ++ ctx->dir, DMA_ATTR_SKIP_CPU_SYNC); caam_jr_free(ctx->jrdev); } -@@ -4515,7 +3405,6 @@ static struct caam_crypto_alg *caam_alg_ +@@ -4515,7 +3415,6 @@ static struct caam_crypto_alg *caam_alg_ t_alg->caam.class1_alg_type = template->class1_alg_type; t_alg->caam.class2_alg_type = template->class2_alg_type; @@ -11206,10 +11235,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + /* VSOL = payloadlen + icvlen + padlen */ + append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, 4); + -+#ifdef __LITTLE_ENDIAN -+ append_moveb(desc, MOVE_WAITCOMP | -+ MOVE_SRC_MATH0 | MOVE_DEST_MATH0 | 8); -+#endif ++ if (caam_little_end) ++ append_moveb(desc, MOVE_WAITCOMP | ++ MOVE_SRC_MATH0 | MOVE_DEST_MATH0 | 8); ++ + /* update Len field */ + append_math_sub(desc, REG0, REG0, REG2, 8); + @@ -11259,15 +11288,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * SEQ OUT PTR command, Output Pointer (2 words) and + * Output Length into math registers. + */ -+#ifdef __LITTLE_ENDIAN -+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_DESCBUF | -+ MOVE_DEST_MATH0 | (55 * 4 << MOVE_OFFSET_SHIFT) | -+ 20); -+#else -+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_DESCBUF | -+ MOVE_DEST_MATH0 | (54 * 4 << MOVE_OFFSET_SHIFT) | -+ 20); -+#endif ++ if (caam_little_end) ++ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_DESCBUF | ++ MOVE_DEST_MATH0 | ++ (55 * 4 << MOVE_OFFSET_SHIFT) | 20); ++ else ++ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_DESCBUF | ++ MOVE_DEST_MATH0 | ++ (54 * 4 << MOVE_OFFSET_SHIFT) | 20); ++ + /* Transform SEQ OUT PTR command in SEQ IN PTR command */ + append_math_and_imm_u32(desc, REG0, REG0, IMM, + ~(CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR)); @@ -11278,15 +11307,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + (4 << LDST_OFFSET_SHIFT)); + append_jump(desc, JUMP_TEST_ALL | JUMP_COND_CALM | 1); + /* Move the updated fields back to the Job Descriptor */ -+#ifdef __LITTLE_ENDIAN -+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_MATH0 | -+ MOVE_DEST_DESCBUF | (55 * 4 << MOVE_OFFSET_SHIFT) | -+ 24); -+#else -+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_MATH0 | -+ MOVE_DEST_DESCBUF | (54 * 4 << MOVE_OFFSET_SHIFT) | -+ 24); -+#endif ++ if (caam_little_end) ++ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_MATH0 | ++ MOVE_DEST_DESCBUF | ++ (55 * 4 << MOVE_OFFSET_SHIFT) | 24); ++ else ++ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_MATH0 | ++ MOVE_DEST_DESCBUF | ++ (54 * 4 << MOVE_OFFSET_SHIFT) | 24); ++ + /* + * Read the new SEQ IN PTR command, Input Pointer, Input Length + * and then jump back to the next command from the @@ -11298,15 +11327,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * Move the SEQ OUT PTR command, Output Pointer (1 word) and + * Output Length into math registers. + */ -+#ifdef __LITTLE_ENDIAN -+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_DESCBUF | -+ MOVE_DEST_MATH0 | (54 * 4 << MOVE_OFFSET_SHIFT) | -+ 12); -+#else -+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_DESCBUF | -+ MOVE_DEST_MATH0 | (53 * 4 << MOVE_OFFSET_SHIFT) | -+ 12); -+#endif ++ if (caam_little_end) ++ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_DESCBUF | ++ MOVE_DEST_MATH0 | ++ (54 * 4 << MOVE_OFFSET_SHIFT) | 12); ++ else ++ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_DESCBUF | ++ MOVE_DEST_MATH0 | ++ (53 * 4 << MOVE_OFFSET_SHIFT) | 12); ++ + /* Transform SEQ OUT PTR command in SEQ IN PTR command */ + append_math_and_imm_u64(desc, REG0, REG0, IMM, + ~(((u64)(CMD_SEQ_IN_PTR ^ @@ -11318,15 +11347,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + (4 << LDST_OFFSET_SHIFT)); + append_jump(desc, JUMP_TEST_ALL | JUMP_COND_CALM | 1); + /* Move the updated fields back to the Job Descriptor */ -+#ifdef __LITTLE_ENDIAN -+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_MATH0 | -+ MOVE_DEST_DESCBUF | (54 * 4 << MOVE_OFFSET_SHIFT) | -+ 16); -+#else -+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_MATH0 | -+ MOVE_DEST_DESCBUF | (53 * 4 << MOVE_OFFSET_SHIFT) | -+ 16); -+#endif ++ if (caam_little_end) ++ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_MATH0 | ++ MOVE_DEST_DESCBUF | ++ (54 * 4 << MOVE_OFFSET_SHIFT) | 16); ++ else ++ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_MATH0 | ++ MOVE_DEST_DESCBUF | ++ (53 * 4 << MOVE_OFFSET_SHIFT) | 16); ++ + /* + * Read the new SEQ IN PTR command, Input Pointer, Input Length + * and then jump back to the next command from the @@ -12406,7 +12435,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#endif /* _CAAMALG_DESC_H_ */ --- /dev/null +++ b/drivers/crypto/caam/caamalg_qi.c -@@ -0,0 +1,2929 @@ +@@ -0,0 +1,3321 @@ +/* + * Freescale FSL CAAM support for crypto API over QI backend. + * Based on caamalg.c @@ -12462,6 +12491,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u32 sh_desc_givenc[DESC_MAX_USED_LEN]; + u8 key[CAAM_MAX_KEY_SIZE]; + dma_addr_t key_dma; ++ enum dma_data_direction dir; + struct alginfo adata; + struct alginfo cdata; + unsigned int authsize; @@ -12640,7 +12670,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + keys.enckeylen); + dma_sync_single_for_device(jrdev, ctx->key_dma, + ctx->adata.keylen_pad + -+ keys.enckeylen, DMA_TO_DEVICE); ++ keys.enckeylen, ctx->dir); + goto skip_split_key; + } + @@ -12653,7 +12683,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + /* postpend encryption key to auth split key */ + memcpy(ctx->key + ctx->adata.keylen_pad, keys.enckey, keys.enckeylen); + dma_sync_single_for_device(jrdev, ctx->key_dma, ctx->adata.keylen_pad + -+ keys.enckeylen, DMA_TO_DEVICE); ++ keys.enckeylen, ctx->dir); +#ifdef DEBUG + print_hex_dump(KERN_ERR, "ctx.key@" __stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, @@ -12796,7 +12826,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + keys.enckeylen); + dma_sync_single_for_device(jrdev, ctx->key_dma, + ctx->adata.keylen_pad + -+ keys.enckeylen, DMA_TO_DEVICE); ++ keys.enckeylen, ctx->dir); + goto skip_split_key; + } + @@ -12809,7 +12839,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + /* postpend encryption key to auth split key */ + memcpy(ctx->key + ctx->adata.keylen_pad, keys.enckey, keys.enckeylen); + dma_sync_single_for_device(jrdev, ctx->key_dma, ctx->adata.keylen_pad + -+ keys.enckeylen, DMA_TO_DEVICE); ++ keys.enckeylen, ctx->dir); + +#ifdef DEBUG + dev_err(jrdev, "split keylen %d split keylen padded %d\n", @@ -12851,6 +12881,309 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return -EINVAL; +} + ++static int gcm_set_sh_desc(struct crypto_aead *aead) ++{ ++ struct caam_ctx *ctx = crypto_aead_ctx(aead); ++ unsigned int ivsize = crypto_aead_ivsize(aead); ++ int rem_bytes = CAAM_DESC_BYTES_MAX - DESC_JOB_IO_LEN - ++ ctx->cdata.keylen; ++ ++ if (!ctx->cdata.keylen || !ctx->authsize) ++ return 0; ++ ++ /* ++ * Job Descriptor and Shared Descriptor ++ * must fit into the 64-word Descriptor h/w Buffer ++ */ ++ if (rem_bytes >= DESC_QI_GCM_ENC_LEN) { ++ ctx->cdata.key_inline = true; ++ ctx->cdata.key_virt = ctx->key; ++ } else { ++ ctx->cdata.key_inline = false; ++ ctx->cdata.key_dma = ctx->key_dma; ++ } ++ ++ cnstr_shdsc_gcm_encap(ctx->sh_desc_enc, &ctx->cdata, ivsize, ++ ctx->authsize, true); ++ ++ /* ++ * Job Descriptor and Shared Descriptor ++ * must fit into the 64-word Descriptor h/w Buffer ++ */ ++ if (rem_bytes >= DESC_QI_GCM_DEC_LEN) { ++ ctx->cdata.key_inline = true; ++ ctx->cdata.key_virt = ctx->key; ++ } else { ++ ctx->cdata.key_inline = false; ++ ctx->cdata.key_dma = ctx->key_dma; ++ } ++ ++ cnstr_shdsc_gcm_decap(ctx->sh_desc_dec, &ctx->cdata, ivsize, ++ ctx->authsize, true); ++ ++ return 0; ++} ++ ++static int gcm_setauthsize(struct crypto_aead *authenc, unsigned int authsize) ++{ ++ struct caam_ctx *ctx = crypto_aead_ctx(authenc); ++ ++ ctx->authsize = authsize; ++ gcm_set_sh_desc(authenc); ++ ++ return 0; ++} ++ ++static int gcm_setkey(struct crypto_aead *aead, ++ const u8 *key, unsigned int keylen) ++{ ++ struct caam_ctx *ctx = crypto_aead_ctx(aead); ++ struct device *jrdev = ctx->jrdev; ++ int ret; ++ ++#ifdef DEBUG ++ print_hex_dump(KERN_ERR, "key in @" __stringify(__LINE__)": ", ++ DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); ++#endif ++ ++ memcpy(ctx->key, key, keylen); ++ dma_sync_single_for_device(jrdev, ctx->key_dma, keylen, ctx->dir); ++ ctx->cdata.keylen = keylen; ++ ++ ret = gcm_set_sh_desc(aead); ++ if (ret) ++ return ret; ++ ++ /* Now update the driver contexts with the new shared descriptor */ ++ if (ctx->drv_ctx[ENCRYPT]) { ++ ret = caam_drv_ctx_update(ctx->drv_ctx[ENCRYPT], ++ ctx->sh_desc_enc); ++ if (ret) { ++ dev_err(jrdev, "driver enc context update failed\n"); ++ return ret; ++ } ++ } ++ ++ if (ctx->drv_ctx[DECRYPT]) { ++ ret = caam_drv_ctx_update(ctx->drv_ctx[DECRYPT], ++ ctx->sh_desc_dec); ++ if (ret) { ++ dev_err(jrdev, "driver dec context update failed\n"); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static int rfc4106_set_sh_desc(struct crypto_aead *aead) ++{ ++ struct caam_ctx *ctx = crypto_aead_ctx(aead); ++ unsigned int ivsize = crypto_aead_ivsize(aead); ++ int rem_bytes = CAAM_DESC_BYTES_MAX - DESC_JOB_IO_LEN - ++ ctx->cdata.keylen; ++ ++ if (!ctx->cdata.keylen || !ctx->authsize) ++ return 0; ++ ++ ctx->cdata.key_virt = ctx->key; ++ ++ /* ++ * Job Descriptor and Shared Descriptor ++ * must fit into the 64-word Descriptor h/w Buffer ++ */ ++ if (rem_bytes >= DESC_QI_RFC4106_ENC_LEN) { ++ ctx->cdata.key_inline = true; ++ } else { ++ ctx->cdata.key_inline = false; ++ ctx->cdata.key_dma = ctx->key_dma; ++ } ++ ++ cnstr_shdsc_rfc4106_encap(ctx->sh_desc_enc, &ctx->cdata, ivsize, ++ ctx->authsize, true); ++ ++ /* ++ * Job Descriptor and Shared Descriptor ++ * must fit into the 64-word Descriptor h/w Buffer ++ */ ++ if (rem_bytes >= DESC_QI_RFC4106_DEC_LEN) { ++ ctx->cdata.key_inline = true; ++ } else { ++ ctx->cdata.key_inline = false; ++ ctx->cdata.key_dma = ctx->key_dma; ++ } ++ ++ cnstr_shdsc_rfc4106_decap(ctx->sh_desc_dec, &ctx->cdata, ivsize, ++ ctx->authsize, true); ++ ++ return 0; ++} ++ ++static int rfc4106_setauthsize(struct crypto_aead *authenc, ++ unsigned int authsize) ++{ ++ struct caam_ctx *ctx = crypto_aead_ctx(authenc); ++ ++ ctx->authsize = authsize; ++ rfc4106_set_sh_desc(authenc); ++ ++ return 0; ++} ++ ++static int rfc4106_setkey(struct crypto_aead *aead, ++ const u8 *key, unsigned int keylen) ++{ ++ struct caam_ctx *ctx = crypto_aead_ctx(aead); ++ struct device *jrdev = ctx->jrdev; ++ int ret; ++ ++ if (keylen < 4) ++ return -EINVAL; ++ ++#ifdef DEBUG ++ print_hex_dump(KERN_ERR, "key in @" __stringify(__LINE__)": ", ++ DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); ++#endif ++ ++ memcpy(ctx->key, key, keylen); ++ /* ++ * The last four bytes of the key material are used as the salt value ++ * in the nonce. Update the AES key length. ++ */ ++ ctx->cdata.keylen = keylen - 4; ++ dma_sync_single_for_device(jrdev, ctx->key_dma, ctx->cdata.keylen, ++ ctx->dir); ++ ++ ret = rfc4106_set_sh_desc(aead); ++ if (ret) ++ return ret; ++ ++ /* Now update the driver contexts with the new shared descriptor */ ++ if (ctx->drv_ctx[ENCRYPT]) { ++ ret = caam_drv_ctx_update(ctx->drv_ctx[ENCRYPT], ++ ctx->sh_desc_enc); ++ if (ret) { ++ dev_err(jrdev, "driver enc context update failed\n"); ++ return ret; ++ } ++ } ++ ++ if (ctx->drv_ctx[DECRYPT]) { ++ ret = caam_drv_ctx_update(ctx->drv_ctx[DECRYPT], ++ ctx->sh_desc_dec); ++ if (ret) { ++ dev_err(jrdev, "driver dec context update failed\n"); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static int rfc4543_set_sh_desc(struct crypto_aead *aead) ++{ ++ struct caam_ctx *ctx = crypto_aead_ctx(aead); ++ unsigned int ivsize = crypto_aead_ivsize(aead); ++ int rem_bytes = CAAM_DESC_BYTES_MAX - DESC_JOB_IO_LEN - ++ ctx->cdata.keylen; ++ ++ if (!ctx->cdata.keylen || !ctx->authsize) ++ return 0; ++ ++ ctx->cdata.key_virt = ctx->key; ++ ++ /* ++ * Job Descriptor and Shared Descriptor ++ * must fit into the 64-word Descriptor h/w Buffer ++ */ ++ if (rem_bytes >= DESC_QI_RFC4543_ENC_LEN) { ++ ctx->cdata.key_inline = true; ++ } else { ++ ctx->cdata.key_inline = false; ++ ctx->cdata.key_dma = ctx->key_dma; ++ } ++ ++ cnstr_shdsc_rfc4543_encap(ctx->sh_desc_enc, &ctx->cdata, ivsize, ++ ctx->authsize, true); ++ ++ /* ++ * Job Descriptor and Shared Descriptor ++ * must fit into the 64-word Descriptor h/w Buffer ++ */ ++ if (rem_bytes >= DESC_QI_RFC4543_DEC_LEN) { ++ ctx->cdata.key_inline = true; ++ } else { ++ ctx->cdata.key_inline = false; ++ ctx->cdata.key_dma = ctx->key_dma; ++ } ++ ++ cnstr_shdsc_rfc4543_decap(ctx->sh_desc_dec, &ctx->cdata, ivsize, ++ ctx->authsize, true); ++ ++ return 0; ++} ++ ++static int rfc4543_setauthsize(struct crypto_aead *authenc, ++ unsigned int authsize) ++{ ++ struct caam_ctx *ctx = crypto_aead_ctx(authenc); ++ ++ ctx->authsize = authsize; ++ rfc4543_set_sh_desc(authenc); ++ ++ return 0; ++} ++ ++static int rfc4543_setkey(struct crypto_aead *aead, ++ const u8 *key, unsigned int keylen) ++{ ++ struct caam_ctx *ctx = crypto_aead_ctx(aead); ++ struct device *jrdev = ctx->jrdev; ++ int ret; ++ ++ if (keylen < 4) ++ return -EINVAL; ++ ++#ifdef DEBUG ++ print_hex_dump(KERN_ERR, "key in @" __stringify(__LINE__)": ", ++ DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); ++#endif ++ ++ memcpy(ctx->key, key, keylen); ++ /* ++ * The last four bytes of the key material are used as the salt value ++ * in the nonce. Update the AES key length. ++ */ ++ ctx->cdata.keylen = keylen - 4; ++ dma_sync_single_for_device(jrdev, ctx->key_dma, ctx->cdata.keylen, ++ ctx->dir); ++ ++ ret = rfc4543_set_sh_desc(aead); ++ if (ret) ++ return ret; ++ ++ /* Now update the driver contexts with the new shared descriptor */ ++ if (ctx->drv_ctx[ENCRYPT]) { ++ ret = caam_drv_ctx_update(ctx->drv_ctx[ENCRYPT], ++ ctx->sh_desc_enc); ++ if (ret) { ++ dev_err(jrdev, "driver enc context update failed\n"); ++ return ret; ++ } ++ } ++ ++ if (ctx->drv_ctx[DECRYPT]) { ++ ret = caam_drv_ctx_update(ctx->drv_ctx[DECRYPT], ++ ctx->sh_desc_dec); ++ if (ret) { ++ dev_err(jrdev, "driver dec context update failed\n"); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ +static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher, + const u8 *key, unsigned int keylen) +{ @@ -13169,8 +13502,18 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + qidev = caam_ctx->qidev; + + if (unlikely(status)) { ++ u32 ssrc = status & JRSTA_SSRC_MASK; ++ u8 err_id = status & JRSTA_CCBERR_ERRID_MASK; ++ + caam_jr_strstatus(qidev, status); -+ ecode = -EIO; ++ /* ++ * verify hw auth check passed else return -EBADMSG ++ */ ++ if (ssrc == JRSTA_SSRC_CCB_ERROR && ++ err_id == JRSTA_CCBERR_ERRID_ICVCHK) ++ ecode = -EBADMSG; ++ else ++ ecode = -EIO; + } + + edesc = container_of(drv_req, typeof(*edesc), drv_req); @@ -13414,6 +13757,22 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return aead_crypt(req, false); +} + ++static int ipsec_gcm_encrypt(struct aead_request *req) ++{ ++ if (req->assoclen < 8) ++ return -EINVAL; ++ ++ return aead_crypt(req, true); ++} ++ ++static int ipsec_gcm_decrypt(struct aead_request *req) ++{ ++ if (req->assoclen < 8) ++ return -EINVAL; ++ ++ return aead_crypt(req, false); ++} ++ +static void tls_done(struct caam_drv_req *drv_req, u32 status) +{ + struct device *qidev; @@ -14168,6 +14527,61 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +}; + +static struct caam_aead_alg driver_aeads[] = { ++ { ++ .aead = { ++ .base = { ++ .cra_name = "rfc4106(gcm(aes))", ++ .cra_driver_name = "rfc4106-gcm-aes-caam-qi", ++ .cra_blocksize = 1, ++ }, ++ .setkey = rfc4106_setkey, ++ .setauthsize = rfc4106_setauthsize, ++ .encrypt = ipsec_gcm_encrypt, ++ .decrypt = ipsec_gcm_decrypt, ++ .ivsize = 8, ++ .maxauthsize = AES_BLOCK_SIZE, ++ }, ++ .caam = { ++ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM, ++ }, ++ }, ++ { ++ .aead = { ++ .base = { ++ .cra_name = "rfc4543(gcm(aes))", ++ .cra_driver_name = "rfc4543-gcm-aes-caam-qi", ++ .cra_blocksize = 1, ++ }, ++ .setkey = rfc4543_setkey, ++ .setauthsize = rfc4543_setauthsize, ++ .encrypt = ipsec_gcm_encrypt, ++ .decrypt = ipsec_gcm_decrypt, ++ .ivsize = 8, ++ .maxauthsize = AES_BLOCK_SIZE, ++ }, ++ .caam = { ++ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM, ++ }, ++ }, ++ /* Galois Counter Mode */ ++ { ++ .aead = { ++ .base = { ++ .cra_name = "gcm(aes)", ++ .cra_driver_name = "gcm-aes-caam-qi", ++ .cra_blocksize = 1, ++ }, ++ .setkey = gcm_setkey, ++ .setauthsize = gcm_setauthsize, ++ .encrypt = aead_encrypt, ++ .decrypt = aead_decrypt, ++ .ivsize = 12, ++ .maxauthsize = AES_BLOCK_SIZE, ++ }, ++ .caam = { ++ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM, ++ } ++ }, + /* single-pass ipsec_esp descriptor */ + { + .aead = { @@ -15006,7 +15420,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct caam_alg_entry caam; +}; + -+static int caam_init_common(struct caam_ctx *ctx, struct caam_alg_entry *caam) ++static int caam_init_common(struct caam_ctx *ctx, struct caam_alg_entry *caam, ++ bool uses_dkp) +{ + struct caam_drv_private *priv; + /* Digest sizes for MD5, SHA1, SHA-224, SHA-256, SHA-384, SHA-512 */ @@ -15030,8 +15445,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return PTR_ERR(ctx->jrdev); + } + ++ priv = dev_get_drvdata(ctx->jrdev->parent); ++ if (priv->era >= 6 && uses_dkp) ++ ctx->dir = DMA_BIDIRECTIONAL; ++ else ++ ctx->dir = DMA_TO_DEVICE; ++ + ctx->key_dma = dma_map_single(ctx->jrdev, ctx->key, sizeof(ctx->key), -+ DMA_TO_DEVICE); ++ ctx->dir); + if (dma_mapping_error(ctx->jrdev, ctx->key_dma)) { + dev_err(ctx->jrdev, "unable to map key\n"); + caam_jr_free(ctx->jrdev); @@ -15058,7 +15479,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + ctx->authsize = 0; + } + -+ priv = dev_get_drvdata(ctx->jrdev->parent); + ctx->qidev = priv->qidev; + + spin_lock_init(&ctx->lock); @@ -15076,7 +15496,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + crypto_alg); + struct caam_ctx *ctx = crypto_tfm_ctx(tfm); + -+ return caam_init_common(ctx, &caam_alg->caam); ++ return caam_init_common(ctx, &caam_alg->caam, false); +} + +static int caam_aead_init(struct crypto_aead *tfm) @@ -15086,7 +15506,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + aead); + struct caam_ctx *ctx = crypto_aead_ctx(tfm); + -+ return caam_init_common(ctx, &caam_alg->caam); ++ return caam_init_common(ctx, &caam_alg->caam, ++ (alg->setkey == aead_setkey) || ++ (alg->setkey == tls_setkey)); +} + +static void caam_exit_common(struct caam_ctx *ctx) @@ -15095,8 +15517,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + caam_drv_ctx_rel(ctx->drv_ctx[DECRYPT]); + caam_drv_ctx_rel(ctx->drv_ctx[GIVENCRYPT]); + -+ dma_unmap_single(ctx->jrdev, ctx->key_dma, sizeof(ctx->key), -+ DMA_TO_DEVICE); ++ dma_unmap_single(ctx->jrdev, ctx->key_dma, sizeof(ctx->key), ctx->dir); + + caam_jr_free(ctx->jrdev); +} @@ -15338,7 +15759,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +MODULE_AUTHOR("Freescale Semiconductor"); --- /dev/null +++ b/drivers/crypto/caam/caamalg_qi2.c -@@ -0,0 +1,5920 @@ +@@ -0,0 +1,5938 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor Inc. + * Copyright 2017 NXP @@ -15373,6 +15794,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * POSSIBILITY OF SUCH DAMAGE. + */ + ++#include <linux/fsl/mc.h> +#include "compat.h" +#include "regs.h" +#include "caamalg_qi2.h" @@ -15384,7 +15806,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#include "key_gen.h" +#include "caamalg_desc.h" +#include "caamhash_desc.h" -+#include "../../../drivers/staging/fsl-mc/include/mc.h" +#include "../../../drivers/staging/fsl-mc/include/dpaa2-io.h" +#include "../../../drivers/staging/fsl-mc/include/dpaa2-fd.h" + @@ -15432,6 +15853,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * @key: virtual address of the key(s): [authentication key], encryption key + * @flc_dma: I/O virtual addresses of the Flow Contexts + * @key_dma: I/O virtual address of the key ++ * @dir: DMA direction for mapping key and Flow Contexts + * @dev: dpseci device + * @adata: authentication algorithm details + * @cdata: encryption algorithm details @@ -15442,6 +15864,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + u8 key[CAAM_MAX_KEY_SIZE]; + dma_addr_t flc_dma[NUM_OP]; + dma_addr_t key_dma; ++ enum dma_data_direction dir; + struct device *dev; + struct alginfo adata; + struct alginfo cdata; @@ -15604,10 +16027,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + ivsize, ctx->authsize, is_rfc3686, nonce, + ctx1_iv_off, true, priv->sec_attr.era); + -+ flc->flc[1] = desc_len(desc); /* SDL */ ++ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ + dma_sync_single_for_device(dev, ctx->flc_dma[ENCRYPT], + sizeof(flc->flc) + desc_bytes(desc), -+ DMA_BIDIRECTIONAL); ++ ctx->dir); + + /* aead_decrypt shared descriptor */ + if (desc_inline_query(DESC_QI_AEAD_DEC_LEN + @@ -15635,10 +16058,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + ivsize, ctx->authsize, alg->caam.geniv, + is_rfc3686, nonce, ctx1_iv_off, true, + priv->sec_attr.era); -+ flc->flc[1] = desc_len(desc); /* SDL */ ++ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ + dma_sync_single_for_device(dev, ctx->flc_dma[DECRYPT], + sizeof(flc->flc) + desc_bytes(desc), -+ DMA_BIDIRECTIONAL); ++ ctx->dir); + + return 0; +} @@ -15702,7 +16125,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + memcpy(ctx->key, keys.authkey, keys.authkeylen); + memcpy(ctx->key + ctx->adata.keylen_pad, keys.enckey, keys.enckeylen); + dma_sync_single_for_device(dev, ctx->key_dma, ctx->adata.keylen_pad + -+ keys.enckeylen, DMA_BIDIRECTIONAL); ++ keys.enckeylen, ctx->dir); +#ifdef DEBUG + print_hex_dump(KERN_ERR, "ctx.key@" __stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, @@ -15843,7 +16266,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + edesc->dst_nents = dst_nents; + edesc->iv_dma = iv_dma; + -+ edesc->assoclen_dma = dma_map_single(dev, &req->assoclen, 4, ++ edesc->assoclen = cpu_to_caam32(req->assoclen); ++ edesc->assoclen_dma = dma_map_single(dev, &edesc->assoclen, 4, + DMA_TO_DEVICE); + if (dma_mapping_error(dev, edesc->assoclen_dma)) { + dev_err(dev, "unable to map assoclen\n"); @@ -16135,10 +16559,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + cnstr_shdsc_tls_encap(desc, &ctx->cdata, &ctx->adata, + assoclen, ivsize, ctx->authsize, blocksize, + priv->sec_attr.era); -+ flc->flc[1] = desc_len(desc); ++ flc->flc[1] = cpu_to_caam32(desc_len(desc)); + dma_sync_single_for_device(dev, ctx->flc_dma[ENCRYPT], + sizeof(flc->flc) + desc_bytes(desc), -+ DMA_BIDIRECTIONAL); ++ ctx->dir); + + /* + * TLS 1.0 decrypt shared descriptor @@ -16152,10 +16576,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + desc = flc->sh_desc; + cnstr_shdsc_tls_decap(desc, &ctx->cdata, &ctx->adata, assoclen, ivsize, + ctx->authsize, blocksize, priv->sec_attr.era); -+ flc->flc[1] = desc_len(desc); /* SDL */ ++ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ + dma_sync_single_for_device(dev, ctx->flc_dma[DECRYPT], + sizeof(flc->flc) + desc_bytes(desc), -+ DMA_BIDIRECTIONAL); ++ ctx->dir); + + return 0; +} @@ -16188,7 +16612,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + memcpy(ctx->key, keys.authkey, keys.authkeylen); + memcpy(ctx->key + ctx->adata.keylen_pad, keys.enckey, keys.enckeylen); + dma_sync_single_for_device(dev, ctx->key_dma, ctx->adata.keylen_pad + -+ keys.enckeylen, DMA_BIDIRECTIONAL); ++ keys.enckeylen, ctx->dir); +#ifdef DEBUG + print_hex_dump(KERN_ERR, "ctx.key@" __stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, @@ -16242,10 +16666,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + flc = &ctx->flc[ENCRYPT]; + desc = flc->sh_desc; + cnstr_shdsc_gcm_encap(desc, &ctx->cdata, ivsize, ctx->authsize, true); -+ flc->flc[1] = desc_len(desc); /* SDL */ ++ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ + dma_sync_single_for_device(dev, ctx->flc_dma[ENCRYPT], + sizeof(flc->flc) + desc_bytes(desc), -+ DMA_BIDIRECTIONAL); ++ ctx->dir); + + /* + * Job Descriptor and Shared Descriptors @@ -16262,10 +16686,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + flc = &ctx->flc[DECRYPT]; + desc = flc->sh_desc; + cnstr_shdsc_gcm_decap(desc, &ctx->cdata, ivsize, ctx->authsize, true); -+ flc->flc[1] = desc_len(desc); /* SDL */ ++ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ + dma_sync_single_for_device(dev, ctx->flc_dma[DECRYPT], + sizeof(flc->flc) + desc_bytes(desc), -+ DMA_BIDIRECTIONAL); ++ ctx->dir); + + return 0; +} @@ -16292,8 +16716,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#endif + + memcpy(ctx->key, key, keylen); -+ dma_sync_single_for_device(dev, ctx->key_dma, keylen, -+ DMA_BIDIRECTIONAL); ++ dma_sync_single_for_device(dev, ctx->key_dma, keylen, ctx->dir); + ctx->cdata.keylen = keylen; + + return gcm_set_sh_desc(aead); @@ -16330,10 +16753,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + desc = flc->sh_desc; + cnstr_shdsc_rfc4106_encap(desc, &ctx->cdata, ivsize, ctx->authsize, + true); -+ flc->flc[1] = desc_len(desc); /* SDL */ ++ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ + dma_sync_single_for_device(dev, ctx->flc_dma[ENCRYPT], + sizeof(flc->flc) + desc_bytes(desc), -+ DMA_BIDIRECTIONAL); ++ ctx->dir); + + /* + * Job Descriptor and Shared Descriptors @@ -16350,10 +16773,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + desc = flc->sh_desc; + cnstr_shdsc_rfc4106_decap(desc, &ctx->cdata, ivsize, ctx->authsize, + true); -+ flc->flc[1] = desc_len(desc); /* SDL */ ++ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ + dma_sync_single_for_device(dev, ctx->flc_dma[DECRYPT], + sizeof(flc->flc) + desc_bytes(desc), -+ DMA_BIDIRECTIONAL); ++ ctx->dir); + + return 0; +} @@ -16390,7 +16813,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + */ + ctx->cdata.keylen = keylen - 4; + dma_sync_single_for_device(dev, ctx->key_dma, ctx->cdata.keylen, -+ DMA_BIDIRECTIONAL); ++ ctx->dir); + + return rfc4106_set_sh_desc(aead); +} @@ -16426,10 +16849,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + desc = flc->sh_desc; + cnstr_shdsc_rfc4543_encap(desc, &ctx->cdata, ivsize, ctx->authsize, + true); -+ flc->flc[1] = desc_len(desc); /* SDL */ ++ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ + dma_sync_single_for_device(dev, ctx->flc_dma[ENCRYPT], + sizeof(flc->flc) + desc_bytes(desc), -+ DMA_BIDIRECTIONAL); ++ ctx->dir); + + /* + * Job Descriptor and Shared Descriptors @@ -16446,10 +16869,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + desc = flc->sh_desc; + cnstr_shdsc_rfc4543_decap(desc, &ctx->cdata, ivsize, ctx->authsize, + true); -+ flc->flc[1] = desc_len(desc); /* SDL */ ++ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ + dma_sync_single_for_device(dev, ctx->flc_dma[DECRYPT], + sizeof(flc->flc) + desc_bytes(desc), -+ DMA_BIDIRECTIONAL); ++ ctx->dir); + + return 0; +} @@ -16486,7 +16909,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + */ + ctx->cdata.keylen = keylen - 4; + dma_sync_single_for_device(dev, ctx->key_dma, ctx->cdata.keylen, -+ DMA_BIDIRECTIONAL); ++ ctx->dir); + + return rfc4543_set_sh_desc(aead); +} @@ -16537,30 +16960,30 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + desc = flc->sh_desc; + cnstr_shdsc_ablkcipher_encap(desc, &ctx->cdata, ivsize, + is_rfc3686, ctx1_iv_off); -+ flc->flc[1] = desc_len(desc); /* SDL */ ++ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ + dma_sync_single_for_device(dev, ctx->flc_dma[ENCRYPT], + sizeof(flc->flc) + desc_bytes(desc), -+ DMA_BIDIRECTIONAL); ++ ctx->dir); + + /* ablkcipher_decrypt shared descriptor */ + flc = &ctx->flc[DECRYPT]; + desc = flc->sh_desc; + cnstr_shdsc_ablkcipher_decap(desc, &ctx->cdata, ivsize, + is_rfc3686, ctx1_iv_off); -+ flc->flc[1] = desc_len(desc); /* SDL */ ++ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ + dma_sync_single_for_device(dev, ctx->flc_dma[DECRYPT], + sizeof(flc->flc) + desc_bytes(desc), -+ DMA_BIDIRECTIONAL); ++ ctx->dir); + + /* ablkcipher_givencrypt shared descriptor */ + flc = &ctx->flc[GIVENCRYPT]; + desc = flc->sh_desc; + cnstr_shdsc_ablkcipher_givencap(desc, &ctx->cdata, + ivsize, is_rfc3686, ctx1_iv_off); -+ flc->flc[1] = desc_len(desc); /* SDL */ ++ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ + dma_sync_single_for_device(dev, ctx->flc_dma[GIVENCRYPT], + sizeof(flc->flc) + desc_bytes(desc), -+ DMA_BIDIRECTIONAL); ++ ctx->dir); + + return 0; +} @@ -16588,19 +17011,19 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + flc = &ctx->flc[ENCRYPT]; + desc = flc->sh_desc; + cnstr_shdsc_xts_ablkcipher_encap(desc, &ctx->cdata); -+ flc->flc[1] = desc_len(desc); /* SDL */ ++ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ + dma_sync_single_for_device(dev, ctx->flc_dma[ENCRYPT], + sizeof(flc->flc) + desc_bytes(desc), -+ DMA_BIDIRECTIONAL); ++ ctx->dir); + + /* xts_ablkcipher_decrypt shared descriptor */ + flc = &ctx->flc[DECRYPT]; + desc = flc->sh_desc; + cnstr_shdsc_xts_ablkcipher_decap(desc, &ctx->cdata); -+ flc->flc[1] = desc_len(desc); /* SDL */ ++ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ + dma_sync_single_for_device(dev, ctx->flc_dma[DECRYPT], + sizeof(flc->flc) + desc_bytes(desc), -+ DMA_BIDIRECTIONAL); ++ ctx->dir); + + return 0; +} @@ -17324,7 +17747,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + struct caam_alg_entry caam; +}; + -+static int caam_cra_init(struct crypto_tfm *tfm) ++static int caam_cra_init(struct crypto_tfm *tfm, bool uses_dkp) +{ + struct crypto_alg *alg = tfm->__crt_alg; + struct caam_crypto_alg *caam_alg = container_of(alg, typeof(*caam_alg), @@ -17340,11 +17763,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + caam_alg->caam.class2_alg_type; + + ctx->dev = caam_alg->caam.dev; ++ ctx->dir = uses_dkp ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE; + + dma_addr = dma_map_single_attrs(ctx->dev, ctx->flc, + offsetof(struct caam_ctx, flc_dma), -+ DMA_BIDIRECTIONAL, -+ DMA_ATTR_SKIP_CPU_SYNC); ++ ctx->dir, DMA_ATTR_SKIP_CPU_SYNC); + if (dma_mapping_error(ctx->dev, dma_addr)) { + dev_err(ctx->dev, "unable to map key, shared descriptors\n"); + return -ENOMEM; @@ -17363,20 +17786,24 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + crypto_ablkcipher_crt(__crypto_ablkcipher_cast(tfm)); + + ablkcipher_tfm->reqsize = sizeof(struct caam_request); -+ return caam_cra_init(tfm); ++ return caam_cra_init(tfm, false); +} + +static int caam_cra_init_aead(struct crypto_aead *tfm) +{ ++ struct aead_alg *alg = crypto_aead_alg(tfm); ++ + crypto_aead_set_reqsize(tfm, sizeof(struct caam_request)); -+ return caam_cra_init(crypto_aead_tfm(tfm)); ++ return caam_cra_init(crypto_aead_tfm(tfm), ++ (alg->setkey == aead_setkey) || ++ (alg->setkey == tls_setkey)); +} + +static void caam_exit_common(struct caam_ctx *ctx) +{ + dma_unmap_single_attrs(ctx->dev, ctx->flc_dma[0], -+ offsetof(struct caam_ctx, flc_dma), -+ DMA_BIDIRECTIONAL, DMA_ATTR_SKIP_CPU_SYNC); ++ offsetof(struct caam_ctx, flc_dma), ctx->dir, ++ DMA_ATTR_SKIP_CPU_SYNC); +} + +static void caam_cra_exit(struct crypto_tfm *tfm) @@ -18891,7 +19318,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + desc = flc->sh_desc; + cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_UPDATE, ctx->ctx_len, + ctx->ctx_len, true, priv->sec_attr.era); -+ flc->flc[1] = desc_len(desc); /* SDL */ ++ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ + dma_sync_single_for_device(ctx->dev, ctx->flc_dma[UPDATE], + desc_bytes(desc), DMA_BIDIRECTIONAL); +#ifdef DEBUG @@ -18905,7 +19332,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + desc = flc->sh_desc; + cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_INIT, ctx->ctx_len, + ctx->ctx_len, false, priv->sec_attr.era); -+ flc->flc[1] = desc_len(desc); /* SDL */ ++ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ + dma_sync_single_for_device(ctx->dev, ctx->flc_dma[UPDATE_FIRST], + desc_bytes(desc), DMA_BIDIRECTIONAL); +#ifdef DEBUG @@ -18919,7 +19346,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + desc = flc->sh_desc; + cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_FINALIZE, digestsize, + ctx->ctx_len, true, priv->sec_attr.era); -+ flc->flc[1] = desc_len(desc); /* SDL */ ++ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ + dma_sync_single_for_device(ctx->dev, ctx->flc_dma[FINALIZE], + desc_bytes(desc), DMA_BIDIRECTIONAL); +#ifdef DEBUG @@ -18933,7 +19360,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + desc = flc->sh_desc; + cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_INITFINAL, digestsize, + ctx->ctx_len, false, priv->sec_attr.era); -+ flc->flc[1] = desc_len(desc); /* SDL */ ++ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ + dma_sync_single_for_device(ctx->dev, ctx->flc_dma[DIGEST], + desc_bytes(desc), DMA_BIDIRECTIONAL); +#ifdef DEBUG @@ -18994,7 +19421,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + append_seq_store(desc, digestsize, LDST_CLASS_2_CCB | + LDST_SRCDST_BYTE_CONTEXT); + -+ flc->flc[1] = desc_len(desc); /* SDL */ ++ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ + flc_dma = dma_map_single(ctx->dev, flc, sizeof(flc->flc) + + desc_bytes(desc), DMA_TO_DEVICE); + if (dma_mapping_error(ctx->dev, flc_dma)) { @@ -20412,6 +20839,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + template->name); + snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", + template->driver_name); ++ t_alg->ahash_alg.setkey = NULL; + } + alg->cra_module = THIS_MODULE; + alg->cra_init = caam_hash_cra_init; @@ -20456,8 +20884,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + /* Register notification callbacks */ + err = dpaa2_io_service_register(NULL, nctx); + if (unlikely(err)) { -+ dev_err(dev, "notification register failed\n"); ++ dev_dbg(dev, "No affine DPIO for cpu %d\n", cpu); + nctx->cb = NULL; ++ /* ++ * If no affine DPIO for this core, there's probably ++ * none available for next cores either. Signal we want ++ * to retry later, in case the DPIO devices weren't ++ * probed yet. ++ */ ++ err = -EPROBE_DEFER; + goto err; + } + @@ -20935,7 +21370,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + /* Obtain a MC portal */ + err = fsl_mc_portal_allocate(dpseci_dev, 0, &priv->mc_io); + if (err) { -+ dev_err(dev, "MC portal allocation failed\n"); ++ if (err == -ENXIO) ++ err = -EPROBE_DEFER; ++ else ++ dev_err(dev, "MC portal allocation failed\n"); ++ + goto err_dma_mask; + } + @@ -21204,7 +21643,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + memset(&fd, 0, sizeof(fd)); + dpaa2_fd_set_format(&fd, dpaa2_fd_list); + dpaa2_fd_set_addr(&fd, req->fd_flt_dma); -+ dpaa2_fd_set_len(&fd, req->fd_flt[1].len); ++ dpaa2_fd_set_len(&fd, dpaa2_fl_get_len(&req->fd_flt[1])); + dpaa2_fd_set_flc(&fd, req->flc_dma); + + /* @@ -21261,7 +21700,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +module_fsl_mc_driver(dpaa2_caam_driver); --- /dev/null +++ b/drivers/crypto/caam/caamalg_qi2.h -@@ -0,0 +1,281 @@ +@@ -0,0 +1,283 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor Inc. + * Copyright 2017 NXP @@ -21418,6 +21857,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * @iv_dma: dma address of iv for checking continuity and link table + * @qm_sg_bytes: length of dma mapped h/w link table + * @qm_sg_dma: bus physical mapped address of h/w link table ++ * @assoclen: associated data length, in CAAM endianness + * @assoclen_dma: bus physical mapped address of req->assoclen + * @sgt: the h/w link table + */ @@ -21427,6 +21867,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + dma_addr_t iv_dma; + int qm_sg_bytes; + dma_addr_t qm_sg_dma; ++ unsigned int assoclen; + dma_addr_t assoclen_dma; +#define CAAM_QI_MAX_AEAD_SG \ + ((CAAM_QI_MEMCACHE_SIZE - offsetof(struct aead_edesc, sgt)) / \ @@ -21568,7 +22009,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> #define DESC_HASH_MAX_USED_BYTES (DESC_AHASH_FINAL_LEN + \ CAAM_MAX_HASH_KEY_SIZE) #define DESC_HASH_MAX_USED_LEN (DESC_HASH_MAX_USED_BYTES / CAAM_CMD_SZ) -@@ -103,20 +96,14 @@ struct caam_hash_ctx { +@@ -103,20 +96,15 @@ struct caam_hash_ctx { u32 sh_desc_update_first[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned; u32 sh_desc_fin[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned; u32 sh_desc_digest[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned; @@ -21578,6 +22019,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> dma_addr_t sh_desc_fin_dma; dma_addr_t sh_desc_digest_dma; - dma_addr_t sh_desc_finup_dma; ++ enum dma_data_direction dir; struct device *jrdev; - u32 alg_type; - u32 alg_op; @@ -21590,7 +22032,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }; /* ahash state */ -@@ -143,6 +130,31 @@ struct caam_export_state { +@@ -143,6 +131,31 @@ struct caam_export_state { int (*finup)(struct ahash_request *req); }; @@ -21622,7 +22064,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> /* Common job descriptor seq in/out ptr routines */ /* Map state->caam_ctx, and append seq_out_ptr command that points to it */ -@@ -175,40 +187,31 @@ static inline dma_addr_t map_seq_out_ptr +@@ -175,40 +188,31 @@ static inline dma_addr_t map_seq_out_ptr return dst_dma; } @@ -21680,7 +22122,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> struct caam_hash_state *state, int ctx_len, struct sec4_sg_entry *sec4_sg, u32 flag) { -@@ -224,124 +227,22 @@ static inline int ctx_map_to_sec4_sg(u32 +@@ -224,124 +228,22 @@ static inline int ctx_map_to_sec4_sg(u32 return 0; } @@ -21807,11 +22249,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_UPDATE, ctx->ctx_len, + ctx->ctx_len, true, ctrlpriv->era); + dma_sync_single_for_device(jrdev, ctx->sh_desc_update_dma, -+ desc_bytes(desc), DMA_TO_DEVICE); ++ desc_bytes(desc), ctx->dir); #ifdef DEBUG print_hex_dump(KERN_ERR, "ahash update shdesc@"__stringify(__LINE__)": ", -@@ -350,17 +251,10 @@ static int ahash_set_sh_desc(struct cryp +@@ -350,17 +252,10 @@ static int ahash_set_sh_desc(struct cryp /* ahash_update_first shared descriptor */ desc = ctx->sh_desc_update_first; @@ -21829,11 +22271,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_INIT, ctx->ctx_len, + ctx->ctx_len, false, ctrlpriv->era); + dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma, -+ desc_bytes(desc), DMA_TO_DEVICE); ++ desc_bytes(desc), ctx->dir); #ifdef DEBUG print_hex_dump(KERN_ERR, "ahash update first shdesc@"__stringify(__LINE__)": ", -@@ -369,53 +263,22 @@ static int ahash_set_sh_desc(struct cryp +@@ -369,53 +264,22 @@ static int ahash_set_sh_desc(struct cryp /* ahash_final shared descriptor */ desc = ctx->sh_desc_fin; @@ -21850,7 +22292,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_FINALIZE, digestsize, + ctx->ctx_len, true, ctrlpriv->era); + dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma, -+ desc_bytes(desc), DMA_TO_DEVICE); ++ desc_bytes(desc), ctx->dir); #ifdef DEBUG print_hex_dump(KERN_ERR, "ahash final shdesc@"__stringify(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, desc, @@ -21891,11 +22333,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_INITFINAL, digestsize, + ctx->ctx_len, false, ctrlpriv->era); + dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma, -+ desc_bytes(desc), DMA_TO_DEVICE); ++ desc_bytes(desc), ctx->dir); #ifdef DEBUG print_hex_dump(KERN_ERR, "ahash digest shdesc@"__stringify(__LINE__)": ", -@@ -426,14 +289,6 @@ static int ahash_set_sh_desc(struct cryp +@@ -426,14 +290,6 @@ static int ahash_set_sh_desc(struct cryp return 0; } @@ -21910,7 +22352,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> /* Digest hash size if it is too large */ static int hash_digest_key(struct caam_hash_ctx *ctx, const u8 *key_in, u32 *keylen, u8 *key_out, u32 digestsize) -@@ -469,7 +324,7 @@ static int hash_digest_key(struct caam_h +@@ -469,7 +325,7 @@ static int hash_digest_key(struct caam_h } /* Job descriptor to perform unkeyed hash on key_in */ @@ -21919,7 +22361,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> OP_ALG_AS_INITFINAL); append_seq_in_ptr(desc, src_dma, *keylen, 0); append_seq_fifo_load(desc, *keylen, FIFOLD_CLASS_CLASS2 | -@@ -513,12 +368,10 @@ static int hash_digest_key(struct caam_h +@@ -513,12 +369,10 @@ static int hash_digest_key(struct caam_h static int ahash_setkey(struct crypto_ahash *ahash, const u8 *key, unsigned int keylen) { @@ -21933,7 +22375,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> int ret; u8 *hashed_key = NULL; -@@ -539,43 +392,29 @@ static int ahash_setkey(struct crypto_ah +@@ -539,43 +393,29 @@ static int ahash_setkey(struct crypto_ah key = hashed_key; } @@ -21995,7 +22437,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> bad_free_key: kfree(hashed_key); crypto_ahash_set_flags(ahash, CRYPTO_TFM_RES_BAD_KEY_LEN); -@@ -604,6 +443,8 @@ static inline void ahash_unmap(struct de +@@ -604,6 +444,8 @@ static inline void ahash_unmap(struct de struct ahash_edesc *edesc, struct ahash_request *req, int dst_len) { @@ -22004,7 +22446,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> if (edesc->src_nents) dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE); if (edesc->dst_dma) -@@ -612,6 +453,12 @@ static inline void ahash_unmap(struct de +@@ -612,6 +454,12 @@ static inline void ahash_unmap(struct de if (edesc->sec4_sg_bytes) dma_unmap_single(dev, edesc->sec4_sg_dma, edesc->sec4_sg_bytes, DMA_TO_DEVICE); @@ -22017,7 +22459,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> } static inline void ahash_unmap_ctx(struct device *dev, -@@ -643,8 +490,7 @@ static void ahash_done(struct device *jr +@@ -643,8 +491,7 @@ static void ahash_done(struct device *jr dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); #endif @@ -22027,7 +22469,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> if (err) caam_jr_strstatus(jrdev, err); -@@ -671,19 +517,19 @@ static void ahash_done_bi(struct device +@@ -671,19 +518,19 @@ static void ahash_done_bi(struct device struct ahash_edesc *edesc; struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); @@ -22050,7 +22492,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> kfree(edesc); #ifdef DEBUG -@@ -713,8 +559,7 @@ static void ahash_done_ctx_src(struct de +@@ -713,8 +560,7 @@ static void ahash_done_ctx_src(struct de dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); #endif @@ -22060,7 +22502,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> if (err) caam_jr_strstatus(jrdev, err); -@@ -741,19 +586,19 @@ static void ahash_done_ctx_dst(struct de +@@ -741,19 +587,19 @@ static void ahash_done_ctx_dst(struct de struct ahash_edesc *edesc; struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); @@ -22083,7 +22525,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> kfree(edesc); #ifdef DEBUG -@@ -835,13 +680,12 @@ static int ahash_update_ctx(struct ahash +@@ -835,13 +681,12 @@ static int ahash_update_ctx(struct ahash struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); struct caam_hash_state *state = ahash_request_ctx(req); struct device *jrdev = ctx->jrdev; @@ -22103,7 +22545,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> int in_len = *buflen + req->nbytes, to_hash; u32 *desc; int src_nents, mapped_nents, sec4_sg_bytes, sec4_sg_src_index; -@@ -890,15 +734,14 @@ static int ahash_update_ctx(struct ahash +@@ -890,15 +735,14 @@ static int ahash_update_ctx(struct ahash edesc->src_nents = src_nents; edesc->sec4_sg_bytes = sec4_sg_bytes; @@ -22123,7 +22565,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> if (mapped_nents) { sg_to_sec4_sg_last(req->src, mapped_nents, -@@ -909,12 +752,10 @@ static int ahash_update_ctx(struct ahash +@@ -909,12 +753,10 @@ static int ahash_update_ctx(struct ahash to_hash - *buflen, *next_buflen, 0); } else { @@ -22138,7 +22580,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> desc = edesc->hw_desc; edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg, -@@ -969,12 +810,9 @@ static int ahash_final_ctx(struct ahash_ +@@ -969,12 +811,9 @@ static int ahash_final_ctx(struct ahash_ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); struct caam_hash_state *state = ahash_request_ctx(req); struct device *jrdev = ctx->jrdev; @@ -22154,7 +22596,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> u32 *desc; int sec4_sg_bytes, sec4_sg_src_index; int digestsize = crypto_ahash_digestsize(ahash); -@@ -994,18 +832,17 @@ static int ahash_final_ctx(struct ahash_ +@@ -994,18 +833,17 @@ static int ahash_final_ctx(struct ahash_ desc = edesc->hw_desc; edesc->sec4_sg_bytes = sec4_sg_bytes; @@ -22179,7 +22621,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg, sec4_sg_bytes, DMA_TO_DEVICE); -@@ -1048,12 +885,9 @@ static int ahash_finup_ctx(struct ahash_ +@@ -1048,12 +886,9 @@ static int ahash_finup_ctx(struct ahash_ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); struct caam_hash_state *state = ahash_request_ctx(req); struct device *jrdev = ctx->jrdev; @@ -22195,7 +22637,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> u32 *desc; int sec4_sg_src_index; int src_nents, mapped_nents; -@@ -1082,7 +916,7 @@ static int ahash_finup_ctx(struct ahash_ +@@ -1082,7 +917,7 @@ static int ahash_finup_ctx(struct ahash_ /* allocate space for base edesc and hw desc commands, link tables */ edesc = ahash_edesc_alloc(ctx, sec4_sg_src_index + mapped_nents, @@ -22204,7 +22646,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> flags); if (!edesc) { dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE); -@@ -1093,14 +927,14 @@ static int ahash_finup_ctx(struct ahash_ +@@ -1093,14 +928,14 @@ static int ahash_finup_ctx(struct ahash_ edesc->src_nents = src_nents; @@ -22223,7 +22665,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> ret = ahash_edesc_add_src(ctx, edesc, req, mapped_nents, sec4_sg_src_index, ctx->ctx_len + buflen, -@@ -1136,15 +970,18 @@ static int ahash_digest(struct ahash_req +@@ -1136,15 +971,18 @@ static int ahash_digest(struct ahash_req { struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); @@ -22244,7 +22686,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> src_nents = sg_nents_for_len(req->src, req->nbytes); if (src_nents < 0) { dev_err(jrdev, "Invalid number of src SG.\n"); -@@ -1215,10 +1052,10 @@ static int ahash_final_no_ctx(struct aha +@@ -1215,10 +1053,10 @@ static int ahash_final_no_ctx(struct aha struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); struct caam_hash_state *state = ahash_request_ctx(req); struct device *jrdev = ctx->jrdev; @@ -22259,7 +22701,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> u32 *desc; int digestsize = crypto_ahash_digestsize(ahash); struct ahash_edesc *edesc; -@@ -1246,7 +1083,6 @@ static int ahash_final_no_ctx(struct aha +@@ -1246,7 +1084,6 @@ static int ahash_final_no_ctx(struct aha dev_err(jrdev, "unable to map dst\n"); goto unmap; } @@ -22267,7 +22709,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> #ifdef DEBUG print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ", -@@ -1276,13 +1112,12 @@ static int ahash_update_no_ctx(struct ah +@@ -1276,13 +1113,12 @@ static int ahash_update_no_ctx(struct ah struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); struct caam_hash_state *state = ahash_request_ctx(req); struct device *jrdev = ctx->jrdev; @@ -22287,7 +22729,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> int in_len = *buflen + req->nbytes, to_hash; int sec4_sg_bytes, src_nents, mapped_nents; struct ahash_edesc *edesc; -@@ -1329,10 +1164,11 @@ static int ahash_update_no_ctx(struct ah +@@ -1329,10 +1165,11 @@ static int ahash_update_no_ctx(struct ah edesc->src_nents = src_nents; edesc->sec4_sg_bytes = sec4_sg_bytes; @@ -22302,7 +22744,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> sg_to_sec4_sg_last(req->src, mapped_nents, edesc->sec4_sg + 1, 0); -@@ -1342,8 +1178,6 @@ static int ahash_update_no_ctx(struct ah +@@ -1342,8 +1179,6 @@ static int ahash_update_no_ctx(struct ah *next_buflen, 0); } @@ -22311,7 +22753,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> desc = edesc->hw_desc; edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg, -@@ -1403,12 +1237,9 @@ static int ahash_finup_no_ctx(struct aha +@@ -1403,12 +1238,9 @@ static int ahash_finup_no_ctx(struct aha struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); struct caam_hash_state *state = ahash_request_ctx(req); struct device *jrdev = ctx->jrdev; @@ -22327,7 +22769,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> u32 *desc; int sec4_sg_bytes, sec4_sg_src_index, src_nents, mapped_nents; int digestsize = crypto_ahash_digestsize(ahash); -@@ -1450,9 +1281,9 @@ static int ahash_finup_no_ctx(struct aha +@@ -1450,9 +1282,9 @@ static int ahash_finup_no_ctx(struct aha edesc->src_nents = src_nents; edesc->sec4_sg_bytes = sec4_sg_bytes; @@ -22340,7 +22782,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> ret = ahash_edesc_add_src(ctx, edesc, req, mapped_nents, 1, buflen, req->nbytes); -@@ -1496,11 +1327,10 @@ static int ahash_update_first(struct aha +@@ -1496,11 +1328,10 @@ static int ahash_update_first(struct aha struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); struct caam_hash_state *state = ahash_request_ctx(req); struct device *jrdev = ctx->jrdev; @@ -22356,7 +22798,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> int to_hash; u32 *desc; int src_nents, mapped_nents; -@@ -1545,7 +1375,6 @@ static int ahash_update_first(struct aha +@@ -1545,7 +1376,6 @@ static int ahash_update_first(struct aha } edesc->src_nents = src_nents; @@ -22364,7 +22806,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> ret = ahash_edesc_add_src(ctx, edesc, req, mapped_nents, 0, 0, to_hash); -@@ -1582,6 +1411,7 @@ static int ahash_update_first(struct aha +@@ -1582,6 +1412,7 @@ static int ahash_update_first(struct aha state->final = ahash_final_no_ctx; scatterwalk_map_and_copy(next_buf, req->src, 0, req->nbytes, 0); @@ -22372,7 +22814,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> } #ifdef DEBUG print_hex_dump(KERN_ERR, "next buf@"__stringify(__LINE__)": ", -@@ -1688,7 +1518,6 @@ struct caam_hash_template { +@@ -1688,7 +1519,6 @@ struct caam_hash_template { unsigned int blocksize; struct ahash_alg template_ahash; u32 alg_type; @@ -22380,7 +22822,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }; /* ahash descriptors */ -@@ -1714,7 +1543,6 @@ static struct caam_hash_template driver_ +@@ -1714,7 +1544,6 @@ static struct caam_hash_template driver_ }, }, .alg_type = OP_ALG_ALGSEL_SHA1, @@ -22388,7 +22830,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, { .name = "sha224", .driver_name = "sha224-caam", -@@ -1736,7 +1564,6 @@ static struct caam_hash_template driver_ +@@ -1736,7 +1565,6 @@ static struct caam_hash_template driver_ }, }, .alg_type = OP_ALG_ALGSEL_SHA224, @@ -22396,7 +22838,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, { .name = "sha256", .driver_name = "sha256-caam", -@@ -1758,7 +1585,6 @@ static struct caam_hash_template driver_ +@@ -1758,7 +1586,6 @@ static struct caam_hash_template driver_ }, }, .alg_type = OP_ALG_ALGSEL_SHA256, @@ -22404,7 +22846,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, { .name = "sha384", .driver_name = "sha384-caam", -@@ -1780,7 +1606,6 @@ static struct caam_hash_template driver_ +@@ -1780,7 +1607,6 @@ static struct caam_hash_template driver_ }, }, .alg_type = OP_ALG_ALGSEL_SHA384, @@ -22412,7 +22854,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, { .name = "sha512", .driver_name = "sha512-caam", -@@ -1802,7 +1627,6 @@ static struct caam_hash_template driver_ +@@ -1802,7 +1628,6 @@ static struct caam_hash_template driver_ }, }, .alg_type = OP_ALG_ALGSEL_SHA512, @@ -22420,7 +22862,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> }, { .name = "md5", .driver_name = "md5-caam", -@@ -1824,14 +1648,12 @@ static struct caam_hash_template driver_ +@@ -1824,14 +1649,12 @@ static struct caam_hash_template driver_ }, }, .alg_type = OP_ALG_ALGSEL_MD5, @@ -22435,23 +22877,27 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> struct ahash_alg ahash_alg; }; -@@ -1853,6 +1675,7 @@ static int caam_hash_cra_init(struct cry +@@ -1853,6 +1676,8 @@ static int caam_hash_cra_init(struct cry HASH_MSG_LEN + SHA256_DIGEST_SIZE, HASH_MSG_LEN + 64, HASH_MSG_LEN + SHA512_DIGEST_SIZE }; + dma_addr_t dma_addr; ++ struct caam_drv_private *priv; /* * Get a Job ring from Job Ring driver to ensure in-order -@@ -1863,11 +1686,31 @@ static int caam_hash_cra_init(struct cry +@@ -1863,11 +1688,34 @@ static int caam_hash_cra_init(struct cry pr_err("Job Ring Device allocation for transform failed\n"); return PTR_ERR(ctx->jrdev); } + ++ priv = dev_get_drvdata(ctx->jrdev->parent); ++ ctx->dir = priv->era >= 6 ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE; ++ + dma_addr = dma_map_single_attrs(ctx->jrdev, ctx->sh_desc_update, + offsetof(struct caam_hash_ctx, + sh_desc_update_dma), -+ DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); ++ ctx->dir, DMA_ATTR_SKIP_CPU_SYNC); + if (dma_mapping_error(ctx->jrdev, dma_addr)) { + dev_err(ctx->jrdev, "unable to map shared descriptors\n"); + caam_jr_free(ctx->jrdev); @@ -22478,7 +22924,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> OP_ALG_ALGSEL_SHIFT]; crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), -@@ -1879,30 +1722,10 @@ static void caam_hash_cra_exit(struct cr +@@ -1879,30 +1727,10 @@ static void caam_hash_cra_exit(struct cr { struct caam_hash_ctx *ctx = crypto_tfm_ctx(tfm); @@ -22509,11 +22955,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + dma_unmap_single_attrs(ctx->jrdev, ctx->sh_desc_update_dma, + offsetof(struct caam_hash_ctx, + sh_desc_update_dma), -+ DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); ++ ctx->dir, DMA_ATTR_SKIP_CPU_SYNC); caam_jr_free(ctx->jrdev); } -@@ -1961,7 +1784,6 @@ caam_hash_alloc(struct caam_hash_templat +@@ -1961,7 +1789,6 @@ caam_hash_alloc(struct caam_hash_templat alg->cra_type = &crypto_ahash_type; t_alg->alg_type = template->alg_type; @@ -24571,7 +25017,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#endif /* DESC_CONSTR_H */ --- /dev/null +++ b/drivers/crypto/caam/dpseci.c -@@ -0,0 +1,859 @@ +@@ -0,0 +1,858 @@ +/* + * Copyright 2013-2016 Freescale Semiconductor Inc. + * Copyright 2017 NXP @@ -24606,8 +25052,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + * POSSIBILITY OF SUCH DAMAGE. + */ + -+#include "../../../drivers/staging/fsl-mc/include/mc-sys.h" -+#include "../../../drivers/staging/fsl-mc/include/mc-cmd.h" ++#include <linux/fsl/mc.h> +#include "../../../drivers/staging/fsl-mc/include/dpopr.h" +#include "dpseci.h" +#include "dpseci_cmd.h" @@ -24631,7 +25076,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +int dpseci_open(struct fsl_mc_io *mc_io, u32 cmd_flags, int dpseci_id, + u16 *token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpseci_cmd_open *cmd_params; + int err; + @@ -24662,7 +25107,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + */ +int dpseci_close(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + cmd.header = mc_encode_cmd_header(DPSECI_CMDID_CLOSE, + cmd_flags, @@ -24695,7 +25140,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +int dpseci_create(struct fsl_mc_io *mc_io, u16 dprc_token, u32 cmd_flags, + const struct dpseci_cfg *cfg, u32 *obj_id) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpseci_cmd_create *cmd_params; + int i, err; + @@ -24735,7 +25180,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +int dpseci_destroy(struct fsl_mc_io *mc_io, u16 dprc_token, u32 cmd_flags, + u32 object_id) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpseci_cmd_destroy *cmd_params; + + cmd.header = mc_encode_cmd_header(DPSECI_CMDID_DESTROY, @@ -24757,7 +25202,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + */ +int dpseci_enable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + cmd.header = mc_encode_cmd_header(DPSECI_CMDID_ENABLE, + cmd_flags, @@ -24775,7 +25220,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + */ +int dpseci_disable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + cmd.header = mc_encode_cmd_header(DPSECI_CMDID_DISABLE, + cmd_flags, @@ -24796,7 +25241,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +int dpseci_is_enabled(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, + int *en) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpseci_rsp_is_enabled *rsp_params; + int err; + @@ -24823,7 +25268,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + */ +int dpseci_reset(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + cmd.header = mc_encode_cmd_header(DPSECI_CMDID_RESET, + cmd_flags, @@ -24845,7 +25290,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +int dpseci_get_irq_enable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, + u8 irq_index, u8 *en) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpseci_cmd_irq_enable *cmd_params; + struct dpseci_rsp_get_irq_enable *rsp_params; + int err; @@ -24883,7 +25328,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +int dpseci_set_irq_enable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, + u8 irq_index, u8 en) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpseci_cmd_irq_enable *cmd_params; + + cmd.header = mc_encode_cmd_header(DPSECI_CMDID_SET_IRQ_ENABLE, @@ -24912,7 +25357,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +int dpseci_get_irq_mask(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, + u8 irq_index, u32 *mask) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpseci_cmd_irq_mask *cmd_params; + int err; + @@ -24949,7 +25394,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +int dpseci_set_irq_mask(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, + u8 irq_index, u32 mask) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpseci_cmd_irq_mask *cmd_params; + + cmd.header = mc_encode_cmd_header(DPSECI_CMDID_SET_IRQ_MASK, @@ -24977,7 +25422,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +int dpseci_get_irq_status(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, + u8 irq_index, u32 *status) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpseci_cmd_irq_status *cmd_params; + int err; + @@ -25011,7 +25456,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +int dpseci_clear_irq_status(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, + u8 irq_index, u32 status) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpseci_cmd_irq_status *cmd_params; + + cmd.header = mc_encode_cmd_header(DPSECI_CMDID_CLEAR_IRQ_STATUS, @@ -25036,7 +25481,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +int dpseci_get_attributes(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, + struct dpseci_attr *attr) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpseci_rsp_get_attributes *rsp_params; + int err; + @@ -25071,7 +25516,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +int dpseci_set_rx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, + u8 queue, const struct dpseci_rx_queue_cfg *cfg) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpseci_cmd_queue *cmd_params; + + cmd.header = mc_encode_cmd_header(DPSECI_CMDID_SET_RX_QUEUE, @@ -25104,7 +25549,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +int dpseci_get_rx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, + u8 queue, struct dpseci_rx_queue_attr *attr) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpseci_cmd_queue *cmd_params; + int err; + @@ -25142,7 +25587,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +int dpseci_get_tx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, + u8 queue, struct dpseci_tx_queue_attr *attr) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpseci_cmd_queue *cmd_params; + struct dpseci_rsp_get_tx_queue *rsp_params; + int err; @@ -25175,7 +25620,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +int dpseci_get_sec_attr(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, + struct dpseci_sec_attr *attr) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpseci_rsp_get_sec_attr *rsp_params; + int err; + @@ -25220,7 +25665,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +int dpseci_get_sec_counters(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, + struct dpseci_sec_counters *counters) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpseci_rsp_get_sec_counters *rsp_params; + int err; + @@ -25256,7 +25701,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +int dpseci_get_api_version(struct fsl_mc_io *mc_io, u32 cmd_flags, + u16 *major_ver, u16 *minor_ver) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpseci_rsp_get_api_version *rsp_params; + int err; + @@ -25288,7 +25733,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +int dpseci_set_opr(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, u8 index, + u8 options, struct opr_cfg *cfg) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpseci_cmd_opr *cmd_params; + + cmd.header = mc_encode_cmd_header( @@ -25321,7 +25766,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +int dpseci_get_opr(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, u8 index, + struct opr_cfg *cfg, struct opr_qry *qry) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpseci_cmd_opr *cmd_params; + struct dpseci_rsp_get_opr *rsp_params; + int err; @@ -25370,7 +25815,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +int dpseci_set_congestion_notification(struct fsl_mc_io *mc_io, u32 cmd_flags, + u16 token, const struct dpseci_congestion_notification_cfg *cfg) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpseci_cmd_congestion_notification *cmd_params; + + cmd.header = mc_encode_cmd_header( @@ -25405,7 +25850,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +int dpseci_get_congestion_notification(struct fsl_mc_io *mc_io, u32 cmd_flags, + u16 token, struct dpseci_congestion_notification_cfg *cfg) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + struct dpseci_cmd_congestion_notification *rsp_params; + int err; + @@ -26735,7 +27180,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +} --- /dev/null +++ b/drivers/crypto/caam/qi.c -@@ -0,0 +1,797 @@ +@@ -0,0 +1,804 @@ +/* + * CAAM/SEC 4.x QI transport/backend driver + * Queue Interface backend functionality @@ -27314,8 +27759,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return qman_cb_dqrr_stop; + + fd = &dqrr->fd; -+ if (unlikely(fd->status)) -+ dev_err(qidev, "Error: %#x in CAAM response FD\n", fd->status); ++ if (unlikely(fd->status)) { ++ u32 ssrc = fd->status & JRSTA_SSRC_MASK; ++ u8 err_id = fd->status & JRSTA_CCBERR_ERRID_MASK; ++ ++ if (ssrc != JRSTA_SSRC_CCB_ERROR || ++ err_id != JRSTA_CCBERR_ERRID_ICVCHK) ++ dev_err(qidev, "Error: %#x in CAAM response FD\n", ++ fd->status); ++ } + + if (unlikely(fd->format != fd->format)) { + dev_err(qidev, "Non-compound FD from CAAM\n"); @@ -28162,6 +28614,23 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> - return sg_nents; -} +#endif /* _SG_SW_SEC4_H_ */ +--- a/drivers/crypto/talitos.c ++++ b/drivers/crypto/talitos.c +@@ -1241,6 +1241,14 @@ static int ipsec_esp(struct talitos_edes + ret = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[4], + sg_count, areq->assoclen, tbl_off, elen); + ++ /* ++ * In case of SEC 2.x+, cipher in len must include only the ciphertext, ++ * while extent is used for ICV len. ++ */ ++ if ((edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP) && ++ (desc->hdr & DESC_HDR_MODE1_MDEU_CICV)) ++ desc->ptr[4].len = cpu_to_be16(cryptlen); ++ + if (ret > 1) { + tbl_off += ret; + sync_needed = true; --- a/drivers/net/wireless/rsi/rsi_91x_usb.c +++ b/drivers/net/wireless/rsi/rsi_91x_usb.c @@ -516,7 +516,7 @@ err: diff --git a/target/linux/layerscape/patches-4.9/805-dma-support-layerscape.patch b/target/linux/layerscape/patches-4.9/805-dma-support-layerscape.patch index 0eeeb9d77f..fb42fdaa5f 100644 --- a/target/linux/layerscape/patches-4.9/805-dma-support-layerscape.patch +++ b/target/linux/layerscape/patches-4.9/805-dma-support-layerscape.patch @@ -1,7 +1,7 @@ -From 515d590e3d5313110faa4f2c86f7784d9b070fa9 Mon Sep 17 00:00:00 2001 +From d3d537ebe9884e7d945ab74bb02312d0c2c9b08d Mon Sep 17 00:00:00 2001 From: Yangbo Lu <yangbo.lu@nxp.com> -Date: Wed, 17 Jan 2018 15:30:59 +0800 -Subject: [PATCH 17/30] dma: support layerscape +Date: Thu, 5 Jul 2018 17:32:53 +0800 +Subject: [PATCH 17/32] dma: support layerscape This is an integrated patch for layerscape dma support. @@ -10,16 +10,16 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- drivers/dma/Kconfig | 31 + drivers/dma/Makefile | 3 + - drivers/dma/caam_dma.c | 563 ++++++++++++++ + drivers/dma/caam_dma.c | 563 ++++++++++ drivers/dma/dpaa2-qdma/Kconfig | 8 + drivers/dma/dpaa2-qdma/Makefile | 8 + - drivers/dma/dpaa2-qdma/dpaa2-qdma.c | 986 ++++++++++++++++++++++++ - drivers/dma/dpaa2-qdma/dpaa2-qdma.h | 262 +++++++ - drivers/dma/dpaa2-qdma/dpdmai.c | 454 +++++++++++ - drivers/dma/dpaa2-qdma/fsl_dpdmai.h | 521 +++++++++++++ - drivers/dma/dpaa2-qdma/fsl_dpdmai_cmd.h | 222 ++++++ - drivers/dma/fsl-qdma.c | 1243 +++++++++++++++++++++++++++++++ - 11 files changed, 4301 insertions(+) + drivers/dma/dpaa2-qdma/dpaa2-qdma.c | 940 +++++++++++++++++ + drivers/dma/dpaa2-qdma/dpaa2-qdma.h | 227 +++++ + drivers/dma/dpaa2-qdma/dpdmai.c | 515 ++++++++++ + drivers/dma/dpaa2-qdma/fsl_dpdmai.h | 521 ++++++++++ + drivers/dma/dpaa2-qdma/fsl_dpdmai_cmd.h | 222 ++++ + drivers/dma/fsl-qdma.c | 1243 +++++++++++++++++++++++ + 11 files changed, 4281 insertions(+) create mode 100644 drivers/dma/caam_dma.c create mode 100644 drivers/dma/dpaa2-qdma/Kconfig create mode 100644 drivers/dma/dpaa2-qdma/Makefile @@ -686,7 +686,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +fsl-dpaa2-qdma-objs := dpaa2-qdma.o dpdmai.o --- /dev/null +++ b/drivers/dma/dpaa2-qdma/dpaa2-qdma.c -@@ -0,0 +1,986 @@ +@@ -0,0 +1,940 @@ +/* + * drivers/dma/dpaa2-qdma/dpaa2-qdma.c + * @@ -723,7 +723,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +#include "../virt-dma.h" + -+#include "../../../drivers/staging/fsl-mc/include/mc.h" ++#include <linux/fsl/mc.h> +#include "../../../drivers/staging/fsl-mc/include/dpaa2-io.h" +#include "../../../drivers/staging/fsl-mc/include/dpaa2-fd.h" +#include "fsl_dpdmai_cmd.h" @@ -786,10 +786,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + comp_temp->fl_bus_addr = comp_temp->fd_bus_addr + + sizeof(struct dpaa2_fd); + comp_temp->desc_virt_addr = -+ (void *)((struct dpaa2_frame_list *) ++ (void *)((struct dpaa2_fl_entry *) + comp_temp->fl_virt_addr + 3); + comp_temp->desc_bus_addr = comp_temp->fl_bus_addr + -+ sizeof(struct dpaa2_frame_list) * 3; ++ sizeof(struct dpaa2_fl_entry) * 3; + + comp_temp->qchan = dpaa2_chan; + comp_temp->sg_blk_num = 0; @@ -816,19 +816,19 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + memset(fd, 0, sizeof(struct dpaa2_fd)); + + /* fd populated */ -+ fd->simple.addr = dpaa2_comp->fl_bus_addr; ++ dpaa2_fd_set_addr(fd, dpaa2_comp->fl_bus_addr); + /* Bypass memory translation, Frame list format, short length disable */ + /* we need to disable BMT if fsl-mc use iova addr */ + if (smmu_disable) -+ fd->simple.bpid = QMAN_FD_BMT_ENABLE; -+ fd->simple.format_offset = QMAN_FD_FMT_ENABLE | QMAN_FD_SL_DISABLE; ++ dpaa2_fd_set_bpid(fd, QMAN_FD_BMT_ENABLE); ++ dpaa2_fd_set_format(fd, QMAN_FD_FMT_ENABLE | QMAN_FD_SL_DISABLE); + -+ fd->simple.frc = format | QDMA_SER_CTX; ++ dpaa2_fd_set_frc(fd, format | QDMA_SER_CTX); +} + +/* first frame list for descriptor buffer */ +static void dpaa2_qdma_populate_first_framel( -+ struct dpaa2_frame_list *f_list, ++ struct dpaa2_fl_entry *f_list, + struct dpaa2_qdma_comp *dpaa2_comp) +{ + struct dpaa2_qdma_sd_d *sdd; @@ -836,48 +836,45 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + sdd = (struct dpaa2_qdma_sd_d *)dpaa2_comp->desc_virt_addr; + memset(sdd, 0, 2 * (sizeof(*sdd))); + /* source and destination descriptor */ -+ sdd->cmd = QDMA_SD_CMD_RDTTYPE_COHERENT; /* source descriptor CMD */ ++ sdd->cmd = cpu_to_le32(QDMA_SD_CMD_RDTTYPE_COHERENT); /* source descriptor CMD */ + sdd++; -+ sdd->cmd = QDMA_DD_CMD_WRTTYPE_COHERENT; /* dest descriptor CMD */ ++ sdd->cmd = cpu_to_le32(QDMA_DD_CMD_WRTTYPE_COHERENT); /* dest descriptor CMD */ + -+ memset(f_list, 0, sizeof(struct dpaa2_frame_list)); ++ memset(f_list, 0, sizeof(struct dpaa2_fl_entry)); + /* first frame list to source descriptor */ -+ f_list->addr_lo = dpaa2_comp->desc_bus_addr; -+ f_list->addr_hi = (dpaa2_comp->desc_bus_addr >> 32); -+ f_list->data_len.data_len_sl0 = 0x20; /* source/destination desc len */ -+ f_list->fmt = QDMA_FL_FMT_SBF; /* single buffer frame */ ++ ++ dpaa2_fl_set_addr(f_list, dpaa2_comp->desc_bus_addr); ++ dpaa2_fl_set_len(f_list, 0x20); ++ dpaa2_fl_set_format(f_list, QDMA_FL_FMT_SBF | QDMA_FL_SL_LONG); ++ + if (smmu_disable) -+ f_list->bmt = QDMA_FL_BMT_ENABLE; /* bypass memory translation */ -+ f_list->sl = QDMA_FL_SL_LONG; /* long length */ -+ f_list->f = 0; /* not the last frame list */ ++ f_list->bpid = cpu_to_le16(QDMA_FL_BMT_ENABLE); /* bypass memory translation */ +} + +/* source and destination frame list */ -+static void dpaa2_qdma_populate_frames(struct dpaa2_frame_list *f_list, ++static void dpaa2_qdma_populate_frames(struct dpaa2_fl_entry *f_list, + dma_addr_t dst, dma_addr_t src, size_t len, uint8_t fmt) +{ + /* source frame list to source buffer */ -+ memset(f_list, 0, sizeof(struct dpaa2_frame_list)); -+ f_list->addr_lo = src; -+ f_list->addr_hi = (src >> 32); -+ f_list->data_len.data_len_sl0 = len; -+ f_list->fmt = fmt; /* single buffer frame or scatter gather frame */ ++ memset(f_list, 0, sizeof(struct dpaa2_fl_entry)); ++ ++ ++ dpaa2_fl_set_addr(f_list, src); ++ dpaa2_fl_set_len(f_list, len); ++ dpaa2_fl_set_format(f_list, (fmt | QDMA_FL_SL_LONG)); /* single buffer frame or scatter gather frame */ + if (smmu_disable) -+ f_list->bmt = QDMA_FL_BMT_ENABLE; /* bypass memory translation */ -+ f_list->sl = QDMA_FL_SL_LONG; /* long length */ -+ f_list->f = 0; /* not the last frame list */ ++ f_list->bpid = cpu_to_le16(QDMA_FL_BMT_ENABLE); /* bypass memory translation */ + + f_list++; + /* destination frame list to destination buffer */ -+ memset(f_list, 0, sizeof(struct dpaa2_frame_list)); -+ f_list->addr_lo = dst; -+ f_list->addr_hi = (dst >> 32); -+ f_list->data_len.data_len_sl0 = len; -+ f_list->fmt = fmt; /* single buffer frame or scatter gather frame */ ++ memset(f_list, 0, sizeof(struct dpaa2_fl_entry)); ++ ++ dpaa2_fl_set_addr(f_list, dst); ++ dpaa2_fl_set_len(f_list, len); ++ dpaa2_fl_set_format(f_list, (fmt | QDMA_FL_SL_LONG)); ++ dpaa2_fl_set_final(f_list, QDMA_FL_F); /* single buffer frame or scatter gather frame */ + if (smmu_disable) -+ f_list->bmt = QDMA_FL_BMT_ENABLE; /* bypass memory translation */ -+ f_list->sl = QDMA_FL_SL_LONG; /* long length */ -+ f_list->f = QDMA_FL_F; /* Final bit: 1, for last frame list */ ++ f_list->bpid = cpu_to_le16(QDMA_FL_BMT_ENABLE); /* bypass memory translation */ +} + +static struct dma_async_tx_descriptor *dpaa2_qdma_prep_memcpy( @@ -886,7 +883,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +{ + struct dpaa2_qdma_chan *dpaa2_chan = to_dpaa2_qdma_chan(chan); + struct dpaa2_qdma_comp *dpaa2_comp; -+ struct dpaa2_frame_list *f_list; ++ struct dpaa2_fl_entry *f_list; + uint32_t format; + + dpaa2_comp = dpaa2_qdma_request_desc(dpaa2_chan); @@ -899,7 +896,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + /* populate Frame descriptor */ + dpaa2_qdma_populate_fd(format, dpaa2_comp); + -+ f_list = (struct dpaa2_frame_list *)dpaa2_comp->fl_virt_addr; ++ f_list = (struct dpaa2_fl_entry *)dpaa2_comp->fl_virt_addr; + +#ifdef LONG_FORMAT + /* first frame list for descriptor buffer (logn format) */ @@ -1062,48 +1059,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return total_len; +} + -+static struct dma_async_tx_descriptor *dpaa2_qdma_prep_sg( -+ struct dma_chan *chan, -+ struct scatterlist *dst_sg, u32 dst_nents, -+ struct scatterlist *src_sg, u32 src_nents, -+ unsigned long flags) -+{ -+ struct dpaa2_qdma_chan *dpaa2_chan = to_dpaa2_qdma_chan(chan); -+ struct dpaa2_qdma_comp *dpaa2_comp; -+ struct dpaa2_frame_list *f_list; -+ struct device *dev = dpaa2_chan->qdma->priv->dev; -+ uint32_t total_len = 0; -+ -+ /* basic sanity checks */ -+ if (dst_nents == 0 || src_nents == 0) -+ return NULL; -+ -+ if (dst_sg == NULL || src_sg == NULL) -+ return NULL; -+ -+ /* get the descriptors required */ -+ dpaa2_comp = dpaa2_qdma_request_desc(dpaa2_chan); -+ -+ /* populate Frame descriptor */ -+ dpaa2_qdma_populate_fd(QDMA_FD_LONG_FORMAT, dpaa2_comp); -+ -+ /* prepare Scatter gather entry for source and destination */ -+ total_len = dpaa2_qdma_populate_sg(dev, dpaa2_chan, -+ dpaa2_comp, dst_sg, dst_nents, src_sg, src_nents); -+ -+ f_list = (struct dpaa2_frame_list *)dpaa2_comp->fl_virt_addr; -+ /* first frame list for descriptor buffer */ -+ dpaa2_qdma_populate_first_framel(f_list, dpaa2_comp); -+ f_list++; -+ /* prepare Scatter gather entry for source and destination */ -+ /* populate source and destination frame list table */ -+ dpaa2_qdma_populate_frames(f_list, dpaa2_comp->sge_dst_bus_addr, -+ dpaa2_comp->sge_src_bus_addr, -+ total_len, QDMA_FL_FMT_SGE); -+ -+ return vchan_tx_prep(&dpaa2_chan->vchan, &dpaa2_comp->vdesc, flags); -+} -+ +static enum dma_status dpaa2_qdma_tx_status(struct dma_chan *chan, + dma_cookie_t cookie, struct dma_tx_state *txstate) +{ @@ -1263,7 +1218,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + /* obtain FD and process the error */ + fd = dpaa2_dq_fd(dq); -+ status = fd->simple.ctrl & 0xff; ++ ++ status = dpaa2_fd_get_ctrl(fd) & 0xff; + if (status) + dev_err(priv->dev, "FD error occurred\n"); + found = 0; @@ -1279,8 +1235,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + fd_eq = (struct dpaa2_fd *) + dpaa2_comp->fd_virt_addr; + -+ if (fd_eq->simple.addr == -+ fd->simple.addr) { ++ if (le64_to_cpu(fd_eq->simple.addr) == ++ le64_to_cpu(fd->simple.addr)) { + + list_del(&dpaa2_comp->list); + list_add_tail(&dpaa2_comp->list, @@ -1574,7 +1530,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + dma_cap_set(DMA_PRIVATE, dpaa2_qdma->dma_dev.cap_mask); + dma_cap_set(DMA_SLAVE, dpaa2_qdma->dma_dev.cap_mask); + dma_cap_set(DMA_MEMCPY, dpaa2_qdma->dma_dev.cap_mask); -+ dma_cap_set(DMA_SG, dpaa2_qdma->dma_dev.cap_mask); + + dpaa2_qdma->dma_dev.dev = dev; + dpaa2_qdma->dma_dev.device_alloc_chan_resources @@ -1583,7 +1538,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + = dpaa2_qdma_free_chan_resources; + dpaa2_qdma->dma_dev.device_tx_status = dpaa2_qdma_tx_status; + dpaa2_qdma->dma_dev.device_prep_dma_memcpy = dpaa2_qdma_prep_memcpy; -+ dpaa2_qdma->dma_dev.device_prep_dma_sg = dpaa2_qdma_prep_sg; + dpaa2_qdma->dma_dev.device_issue_pending = dpaa2_qdma_issue_pending; + + err = dma_async_device_register(&dpaa2_qdma->dma_dev); @@ -1675,7 +1629,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +MODULE_LICENSE("Dual BSD/GPL"); --- /dev/null +++ b/drivers/dma/dpaa2-qdma/dpaa2-qdma.h -@@ -0,0 +1,262 @@ +@@ -0,0 +1,227 @@ +/* Copyright 2015 NXP Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without @@ -1777,7 +1731,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + } ctrl; +} __attribute__((__packed__)); + -+#define QMAN_FD_FMT_ENABLE (1 << 12) /* frame list table enable */ ++#define QMAN_FD_FMT_ENABLE (1) /* frame list table enable */ +#define QMAN_FD_BMT_ENABLE (1 << 15) /* bypass memory translation */ +#define QMAN_FD_BMT_DISABLE (0 << 15) /* bypass memory translation */ +#define QMAN_FD_SL_DISABLE (0 << 14) /* short lengthe disabled */ @@ -1802,49 +1756,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#define QMAN_FD_CBMT_DISABLE (0 << 15) /* Flow Context: 64bit virtual address */ +#define QMAN_FD_SC_DISABLE (0 << 27) /* stashing control */ + -+#define QDMA_FL_FMT_SBF 0x0 /* Single buffer frame */ ++#define QDMA_FL_FMT_SBF (0x0) /* Single buffer frame */ +#define QDMA_FL_FMT_SGE 0x2 /* Scatter gather frame */ -+#define QDMA_FL_BMT_ENABLE 0x1 /* enable bypass memory translation */ ++#define QDMA_FL_BMT_ENABLE (0x1 << 15)/* enable bypass memory translation */ +#define QDMA_FL_BMT_DISABLE 0x0 /* enable bypass memory translation */ -+#define QDMA_FL_SL_LONG 0x0 /* long length */ ++#define QDMA_FL_SL_LONG (0x0 << 2)/* long length */ +#define QDMA_FL_SL_SHORT 0x1 /* short length */ -+#define QDMA_FL_F 0x1 /* last frame list bit */ ++#define QDMA_FL_F (0x1)/* last frame list bit */ +/*Description of Frame list table structure*/ -+struct dpaa2_frame_list { -+ uint32_t addr_lo; /* lower 32 bits of address */ -+ uint32_t addr_hi:17; /* upper 17 bits of address */ -+ uint32_t resrvd:15; -+ union { -+ uint32_t data_len_sl0; /* If SL=0, then data length is 32 */ -+ struct { -+ uint32_t data_len:18; /* IF SL=1; length is 18bit */ -+ uint32_t resrvd:2; -+ uint32_t mem:12; /* Valid only when SL=1 */ -+ } data_len_sl1; -+ } data_len; -+ /* word 4 */ -+ uint32_t bpid:14; /* Frame buffer pool ID */ -+ uint32_t ivp:1; /* Invalid Pool ID. */ -+ uint32_t bmt:1; /* Bypass Memory Translation */ -+ uint32_t offset:12; /* Frame offset */ -+ uint32_t fmt:2; /* Frame Format */ -+ uint32_t sl:1; /* Short Length */ -+ uint32_t f:1; /* Final bit */ -+ -+ uint32_t frc; /* Frame Context */ -+ /* word 6 */ -+ uint32_t err:8; /* Frame errors */ -+ uint32_t resrvd0:8; -+ uint32_t asal:4; /* accelerator-specific annotation length */ -+ uint32_t resrvd1:1; -+ uint32_t ptv2:1; -+ uint32_t ptv1:1; -+ uint32_t pta:1; /* pass-through annotation */ -+ uint32_t resrvd2:8; -+ -+ uint32_t flc_lo; /* lower 32 bits fo flow context */ -+ uint32_t flc_hi; /* higher 32 bits fo flow context */ -+} __attribute__((__packed__)); + +struct dpaa2_qdma_chan { + struct virt_dma_chan vchan; @@ -1931,7 +1850,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + +/* FD pool size: one FD + 3 Frame list + 2 source/destination descriptor */ +#define FD_POOL_SIZE (sizeof(struct dpaa2_fd) + \ -+ sizeof(struct dpaa2_frame_list) * 3 + \ ++ sizeof(struct dpaa2_fl_entry) * 3 + \ + sizeof(struct dpaa2_qdma_sd_d) * 2) + +/* qdma_sg_blk + 16 SGs */ @@ -1940,7 +1859,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#endif /* __DPAA2_QDMA_H */ --- /dev/null +++ b/drivers/dma/dpaa2-qdma/dpdmai.c -@@ -0,0 +1,454 @@ +@@ -0,0 +1,515 @@ +/* Copyright 2013-2015 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without @@ -1976,22 +1895,56 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#include <linux/io.h> +#include "fsl_dpdmai.h" +#include "fsl_dpdmai_cmd.h" -+#include "../../../drivers/staging/fsl-mc/include/mc-sys.h" -+#include "../../../drivers/staging/fsl-mc/include/mc-cmd.h" ++#include <linux/fsl/mc.h> ++ ++struct dpdmai_cmd_open { ++ __le32 dpdmai_id; ++}; ++ ++struct dpdmai_rsp_get_attributes { ++ __le32 id; ++ u8 num_of_priorities; ++ u8 pad0[3]; ++ __le16 major; ++ __le16 minor; ++}; ++ ++ ++struct dpdmai_cmd_queue { ++ __le32 dest_id; ++ u8 priority; ++ u8 queue; ++ u8 dest_type; ++ u8 pad; ++ __le64 user_ctx; ++ union { ++ __le32 options; ++ __le32 fqid; ++ }; ++}; ++ ++struct dpdmai_rsp_get_tx_queue { ++ __le64 pad; ++ __le32 fqid; ++}; ++ + +int dpdmai_open(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + int dpdmai_id, + uint16_t *token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; ++ struct dpdmai_cmd_open *cmd_params; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_OPEN, + cmd_flags, + 0); -+ DPDMAI_CMD_OPEN(cmd, dpdmai_id); ++ ++ cmd_params = (struct dpdmai_cmd_open *)cmd.params; ++ cmd_params->dpdmai_id = cpu_to_le32(dpdmai_id); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); @@ -1999,8 +1952,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return err; + + /* retrieve response parameters */ -+ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); -+ ++ *token = mc_cmd_hdr_read_token(&cmd); + return 0; +} + @@ -2008,7 +1960,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint32_t cmd_flags, + uint16_t token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_CLOSE, @@ -2023,7 +1975,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + const struct dpdmai_cfg *cfg, + uint16_t *token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ @@ -2047,7 +1999,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint32_t cmd_flags, + uint16_t token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_DESTROY, @@ -2062,7 +2014,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint32_t cmd_flags, + uint16_t token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_ENABLE, @@ -2077,7 +2029,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint32_t cmd_flags, + uint16_t token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_DISABLE, @@ -2093,7 +2045,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint16_t token, + int *en) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_IS_ENABLED, @@ -2115,7 +2067,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint32_t cmd_flags, + uint16_t token) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_RESET, @@ -2133,7 +2085,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + int *type, + struct dpdmai_irq_cfg *irq_cfg) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ @@ -2159,7 +2111,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint8_t irq_index, + struct dpdmai_irq_cfg *irq_cfg) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_SET_IRQ, @@ -2177,7 +2129,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint8_t irq_index, + uint8_t *en) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ @@ -2203,7 +2155,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint8_t irq_index, + uint8_t en) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_SET_IRQ_ENABLE, @@ -2221,7 +2173,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint8_t irq_index, + uint32_t *mask) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ @@ -2247,7 +2199,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint8_t irq_index, + uint32_t mask) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_SET_IRQ_MASK, @@ -2265,7 +2217,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint8_t irq_index, + uint32_t *status) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ @@ -2291,7 +2243,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint8_t irq_index, + uint32_t status) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_CLEAR_IRQ_STATUS, @@ -2308,8 +2260,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint16_t token, + struct dpdmai_attr *attr) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; + int err; ++ struct dpdmai_rsp_get_attributes *rsp_params; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_GET_ATTR, @@ -2322,7 +2275,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return err; + + /* retrieve response parameters */ -+ DPDMAI_RSP_GET_ATTR(cmd, attr); ++ rsp_params = (struct dpdmai_rsp_get_attributes *)cmd.params; ++ attr->id = le32_to_cpu(rsp_params->id); ++ attr->version.major = le16_to_cpu(rsp_params->major); ++ attr->version.minor = le16_to_cpu(rsp_params->minor); ++ attr->num_of_priorities = rsp_params->num_of_priorities; ++ + + return 0; +} @@ -2333,13 +2291,22 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint8_t priority, + const struct dpdmai_rx_queue_cfg *cfg) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; ++ struct dpdmai_cmd_queue *cmd_params; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_SET_RX_QUEUE, + cmd_flags, + token); -+ DPDMAI_CMD_SET_RX_QUEUE(cmd, priority, cfg); ++ ++ cmd_params = (struct dpdmai_cmd_queue *)cmd.params; ++ cmd_params->dest_id = cpu_to_le32(cfg->dest_cfg.dest_id); ++ cmd_params->priority = cfg->dest_cfg.priority; ++ cmd_params->queue = priority; ++ cmd_params->dest_type = cfg->dest_cfg.dest_type; ++ cmd_params->user_ctx = cpu_to_le64(cfg->user_ctx); ++ cmd_params->options = cpu_to_le32(cfg->options); ++ + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); @@ -2350,14 +2317,17 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint16_t token, + uint8_t priority, struct dpdmai_rx_queue_attr *attr) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; ++ struct dpdmai_cmd_queue *cmd_params; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_GET_RX_QUEUE, + cmd_flags, + token); -+ DPDMAI_CMD_GET_RX_QUEUE(cmd, priority); ++ ++ cmd_params = (struct dpdmai_cmd_queue *)cmd.params; ++ cmd_params->queue = priority; + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); @@ -2365,7 +2335,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return err; + + /* retrieve response parameters */ -+ DPDMAI_RSP_GET_RX_QUEUE(cmd, attr); ++ attr->dest_cfg.dest_id = le32_to_cpu(cmd_params->dest_id); ++ attr->dest_cfg.priority = cmd_params->priority; ++ attr->dest_cfg.dest_type = cmd_params->dest_type; ++ attr->user_ctx = le64_to_cpu(cmd_params->user_ctx); ++ attr->fqid = le32_to_cpu(cmd_params->fqid); + + return 0; +} @@ -2376,14 +2350,18 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint8_t priority, + struct dpdmai_tx_queue_attr *attr) +{ -+ struct mc_command cmd = { 0 }; ++ struct fsl_mc_command cmd = { 0 }; ++ struct dpdmai_cmd_queue *cmd_params; ++ struct dpdmai_rsp_get_tx_queue *rsp_params; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_GET_TX_QUEUE, + cmd_flags, + token); -+ DPDMAI_CMD_GET_TX_QUEUE(cmd, priority); ++ ++ cmd_params = (struct dpdmai_cmd_queue *)cmd.params; ++ cmd_params->queue = priority; + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); @@ -2391,7 +2369,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + return err; + + /* retrieve response parameters */ -+ DPDMAI_RSP_GET_TX_QUEUE(cmd, attr); ++ ++ rsp_params = (struct dpdmai_rsp_get_tx_queue *)cmd.params; ++ attr->fqid = le32_to_cpu(rsp_params->fqid); + + return 0; +} diff --git a/target/linux/layerscape/patches-4.9/810-iommu-support-layerscape.patch b/target/linux/layerscape/patches-4.9/810-iommu-support-layerscape.patch index 816abbb9e7..afd29e4fe2 100644 --- a/target/linux/layerscape/patches-4.9/810-iommu-support-layerscape.patch +++ b/target/linux/layerscape/patches-4.9/810-iommu-support-layerscape.patch @@ -1,7 +1,7 @@ -From 0a6c701f92e1aa368c44632fa0985e92703354ed Mon Sep 17 00:00:00 2001 +From 89a1f0d7826df69d8e02268b97bc3da02e07203f Mon Sep 17 00:00:00 2001 From: Yangbo Lu <yangbo.lu@nxp.com> -Date: Wed, 17 Jan 2018 15:35:48 +0800 -Subject: [PATCH 22/30] iommu: support layerscape +Date: Thu, 5 Jul 2018 17:35:15 +0800 +Subject: [PATCH 22/32] iommu: support layerscape This is an integrated patch for layerscape smmu support. @@ -11,17 +11,17 @@ Signed-off-by: Nipun Gupta <nipun.gupta@nxp.com> Signed-off-by: Sunil Goutham <sgoutham@cavium.com> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- - drivers/iommu/amd_iommu.c | 56 ++++++---- - drivers/iommu/arm-smmu-v3.c | 111 ++++++++++++++------ - drivers/iommu/arm-smmu.c | 100 +++++++++++++++--- - drivers/iommu/dma-iommu.c | 242 ++++++++++++++++++++++++++++++++++++------- - drivers/iommu/intel-iommu.c | 92 ++++++++++++---- - drivers/iommu/iommu.c | 219 ++++++++++++++++++++++++++++++++++++--- + drivers/iommu/amd_iommu.c | 56 +++++--- + drivers/iommu/arm-smmu-v3.c | 111 +++++++++++----- + drivers/iommu/arm-smmu.c | 100 ++++++++++++--- + drivers/iommu/dma-iommu.c | 242 +++++++++++++++++++++++++++++------ + drivers/iommu/intel-iommu.c | 92 ++++++++++--- + drivers/iommu/iommu.c | 240 ++++++++++++++++++++++++++++++++-- drivers/iommu/mtk_iommu.c | 2 + drivers/iommu/mtk_iommu_v1.c | 2 + include/linux/dma-iommu.h | 11 ++ - include/linux/iommu.h | 55 +++++++--- - 10 files changed, 739 insertions(+), 151 deletions(-) + include/linux/iommu.h | 57 +++++++-- + 10 files changed, 762 insertions(+), 151 deletions(-) --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -312,7 +312,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> out_unlock: mutex_unlock(&smmu_domain->init_mutex); return ret; -@@ -1712,6 +1723,9 @@ arm_smmu_iova_to_phys(struct iommu_domai +@@ -1695,6 +1706,9 @@ arm_smmu_unmap(struct iommu_domain *doma struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); struct io_pgtable_ops *ops = smmu_domain->pgtbl_ops; @@ -398,7 +398,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> #include <linux/spinlock.h> #include <linux/amba/bus.h> -+#include "../staging/fsl-mc/include/mc-bus.h" ++#include <linux/fsl/mc.h> #include "io-pgtable.h" @@ -1132,7 +1132,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> static void quirk_iommu_g4x_gfx(struct pci_dev *dev) --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c -@@ -36,6 +36,7 @@ +@@ -33,9 +33,11 @@ + #include <linux/bitops.h> + #include <linux/property.h> + #include <trace/events/iommu.h> ++#include <linux/fsl/mc.h> static struct kset *iommu_group_kset; static DEFINE_IDA(iommu_group_ida); @@ -1140,7 +1144,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> struct iommu_callback_data { const struct iommu_ops *ops; -@@ -68,6 +69,13 @@ struct iommu_group_attribute { +@@ -68,6 +70,13 @@ struct iommu_group_attribute { const char *buf, size_t count); }; @@ -1154,7 +1158,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> #define IOMMU_GROUP_ATTR(_name, _mode, _show, _store) \ struct iommu_group_attribute iommu_group_attr_##_name = \ __ATTR(_name, _mode, _show, _store) -@@ -86,6 +94,18 @@ static int __iommu_attach_group(struct i +@@ -86,6 +95,18 @@ static int __iommu_attach_group(struct i static void __iommu_detach_group(struct iommu_domain *domain, struct iommu_group *group); @@ -1173,7 +1177,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> static ssize_t iommu_group_attr_show(struct kobject *kobj, struct attribute *__attr, char *buf) { -@@ -133,8 +153,131 @@ static ssize_t iommu_group_show_name(str +@@ -133,8 +154,131 @@ static ssize_t iommu_group_show_name(str return sprintf(buf, "%s\n", group->name); } @@ -1305,7 +1309,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> static void iommu_group_release(struct kobject *kobj) { struct iommu_group *group = to_iommu_group(kobj); -@@ -212,6 +355,11 @@ struct iommu_group *iommu_group_alloc(vo +@@ -212,6 +356,11 @@ struct iommu_group *iommu_group_alloc(vo */ kobject_put(&group->kobj); @@ -1317,7 +1321,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> pr_debug("Allocated group %d\n", group->id); return group; -@@ -318,7 +466,7 @@ static int iommu_group_create_direct_map +@@ -318,7 +467,7 @@ static int iommu_group_create_direct_map struct device *dev) { struct iommu_domain *domain = group->default_domain; @@ -1326,7 +1330,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> struct list_head mappings; unsigned long pg_size; int ret = 0; -@@ -331,18 +479,21 @@ static int iommu_group_create_direct_map +@@ -331,18 +480,21 @@ static int iommu_group_create_direct_map pg_size = 1UL << __ffs(domain->pgsize_bitmap); INIT_LIST_HEAD(&mappings); @@ -1351,7 +1355,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> for (addr = start; addr < end; addr += pg_size) { phys_addr_t phys_addr; -@@ -358,7 +509,7 @@ static int iommu_group_create_direct_map +@@ -358,7 +510,7 @@ static int iommu_group_create_direct_map } out: @@ -1360,7 +1364,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> return ret; } -@@ -563,6 +714,19 @@ struct iommu_group *iommu_group_get(stru +@@ -563,6 +715,19 @@ struct iommu_group *iommu_group_get(stru EXPORT_SYMBOL_GPL(iommu_group_get); /** @@ -1380,7 +1384,34 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> * iommu_group_put - Decrement group reference * @group: the group to use * -@@ -845,10 +1009,19 @@ struct iommu_group *iommu_group_get_for_ +@@ -812,6 +977,26 @@ struct iommu_group *pci_device_group(str + return group; + } + ++/* Get the IOMMU group for device on fsl-mc bus */ ++struct iommu_group *fsl_mc_device_group(struct device *dev) ++{ ++ struct device *cont_dev = fsl_mc_cont_dev(dev); ++ struct iommu_group *group; ++ ++ /* Container device is responsible for creating the iommu group */ ++ if (fsl_mc_is_cont_dev(dev)) { ++ group = iommu_group_alloc(); ++ if (IS_ERR(group)) ++ return NULL; ++ } else { ++ get_device(cont_dev); ++ group = iommu_group_get(cont_dev); ++ put_device(cont_dev); ++ } ++ ++ return group; ++} ++ + /** + * iommu_group_get_for_dev - Find or create the IOMMU group for a device + * @dev: target device +@@ -845,10 +1030,19 @@ struct iommu_group *iommu_group_get_for_ * IOMMU driver. */ if (!group->default_domain) { @@ -1403,7 +1434,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> } ret = iommu_group_add_device(group, dev); -@@ -1557,20 +1730,38 @@ int iommu_domain_set_attr(struct iommu_d +@@ -1557,20 +1751,38 @@ int iommu_domain_set_attr(struct iommu_d } EXPORT_SYMBOL_GPL(iommu_domain_set_attr); @@ -1604,7 +1635,16 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> extern void iommu_group_put(struct iommu_group *group); extern int iommu_group_register_notifier(struct iommu_group *group, struct notifier_block *nb); -@@ -439,16 +460,22 @@ static inline void iommu_set_fault_handl +@@ -330,6 +351,8 @@ static inline size_t iommu_map_sg(struct + extern struct iommu_group *pci_device_group(struct device *dev); + /* Generic device grouping function */ + extern struct iommu_group *generic_device_group(struct device *dev); ++/* FSL-MC device grouping function */ ++struct iommu_group *fsl_mc_device_group(struct device *dev); + + /** + * struct iommu_fwspec - per-device IOMMU instance data +@@ -439,16 +462,22 @@ static inline void iommu_set_fault_handl { } diff --git a/target/linux/layerscape/patches-4.9/811-irqchip-support-layerscape.patch b/target/linux/layerscape/patches-4.9/811-irqchip-support-layerscape.patch index 3a44f26432..3aca252675 100644 --- a/target/linux/layerscape/patches-4.9/811-irqchip-support-layerscape.patch +++ b/target/linux/layerscape/patches-4.9/811-irqchip-support-layerscape.patch @@ -1,7 +1,7 @@ -From 5a5ff01c790d49c0f6fd247f68f2fd9a2128ea91 Mon Sep 17 00:00:00 2001 +From dab02a7cc54494740e849cd51b554d100eb5541d Mon Sep 17 00:00:00 2001 From: Yangbo Lu <yangbo.lu@nxp.com> -Date: Wed, 17 Jan 2018 15:36:28 +0800 -Subject: [PATCH 23/30] irqchip: support layerscape +Date: Thu, 5 Jul 2018 17:36:09 +0800 +Subject: [PATCH 23/32] irqchip: support layerscape This is an integrated patch for layerscape gic support. @@ -9,16 +9,17 @@ Signed-off-by: Eric Auger <eric.auger@redhat.com> Signed-off-by: Zhao Qiang <qiang.zhao@nxp.com> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- - drivers/irqchip/Makefile | 1 + - drivers/irqchip/irq-gic-v3-its.c | 1 + - include/linux/irqdomain.h | 36 ++++++++++++++++++++++++++++++++++++ - kernel/irq/irqdomain.c | 39 +++++++++++++++++++++++++++++++++++++++ - kernel/irq/msi.c | 4 ++-- - 5 files changed, 79 insertions(+), 2 deletions(-) + drivers/irqchip/Makefile | 1 + + drivers/irqchip/irq-gic-v3-its.c | 1 + + include/linux/irqchip/arm-gic-v3.h | 3 +++ + include/linux/irqdomain.h | 36 +++++++++++++++++++++++++++ + kernel/irq/irqdomain.c | 39 ++++++++++++++++++++++++++++++ + kernel/irq/msi.c | 4 +-- + 6 files changed, 82 insertions(+), 2 deletions(-) --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile -@@ -74,3 +74,4 @@ obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scf +@@ -75,3 +75,4 @@ obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scf obj-$(CONFIG_EZNPS_GIC) += irq-eznps.o obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o obj-$(CONFIG_STM32_EXTI) += irq-stm32-exti.o @@ -33,9 +34,21 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> info->ops = &its_msi_domain_ops; info->data = its; inner_domain->host_data = info; +--- a/include/linux/irqchip/arm-gic-v3.h ++++ b/include/linux/irqchip/arm-gic-v3.h +@@ -133,6 +133,9 @@ + #define GIC_BASER_SHAREABILITY(reg, type) \ + (GIC_BASER_##type << reg##_SHAREABILITY_SHIFT) + ++/* encode a size field of width @w containing @n - 1 units */ ++#define GIC_ENCODE_SZ(n, w) (((unsigned long)(n) - 1) & GENMASK_ULL(((w) - 1), 0)) ++ + #define GICR_PROPBASER_SHAREABILITY_SHIFT (10) + #define GICR_PROPBASER_INNER_CACHEABILITY_SHIFT (7) + #define GICR_PROPBASER_OUTER_CACHEABILITY_SHIFT (56) --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h -@@ -183,6 +183,12 @@ enum { +@@ -187,6 +187,12 @@ enum { /* Irq domain is an IPI domain with single virq */ IRQ_DOMAIN_FLAG_IPI_SINGLE = (1 << 3), @@ -48,7 +61,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> /* * Flags starting from IRQ_DOMAIN_FLAG_NONCORE are reserved * for implementation specific purposes and ignored by the -@@ -216,6 +222,7 @@ struct irq_domain *irq_domain_add_legacy +@@ -220,6 +226,7 @@ struct irq_domain *irq_domain_add_legacy void *host_data); extern struct irq_domain *irq_find_matching_fwspec(struct irq_fwspec *fwspec, enum irq_domain_bus_token bus_token); @@ -56,7 +69,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> extern void irq_set_default_host(struct irq_domain *host); extern int irq_domain_alloc_descs(int virq, unsigned int nr_irqs, irq_hw_number_t hwirq, int node, -@@ -446,6 +453,19 @@ static inline bool irq_domain_is_ipi_sin +@@ -453,6 +460,19 @@ static inline bool irq_domain_is_ipi_sin { return domain->flags & IRQ_DOMAIN_FLAG_IPI_SINGLE; } @@ -76,7 +89,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> #else /* CONFIG_IRQ_DOMAIN_HIERARCHY */ static inline void irq_domain_activate_irq(struct irq_data *data) { } static inline void irq_domain_deactivate_irq(struct irq_data *data) { } -@@ -477,6 +497,22 @@ static inline bool irq_domain_is_ipi_sin +@@ -484,6 +504,22 @@ static inline bool irq_domain_is_ipi_sin { return false; } @@ -101,7 +114,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> #else /* CONFIG_IRQ_DOMAIN */ --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c -@@ -278,6 +278,31 @@ struct irq_domain *irq_find_matching_fws +@@ -319,6 +319,31 @@ struct irq_domain *irq_find_matching_fws EXPORT_SYMBOL_GPL(irq_find_matching_fwspec); /** @@ -133,7 +146,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> * irq_set_default_host() - Set a "default" irq domain * @domain: default domain pointer * -@@ -1408,6 +1433,20 @@ static void irq_domain_check_hierarchy(s +@@ -1420,6 +1445,20 @@ static void irq_domain_check_hierarchy(s if (domain->ops->alloc) domain->flags |= IRQ_DOMAIN_FLAG_HIERARCHY; } diff --git a/target/linux/layerscape/patches-4.9/817-usb-support-layerscape.patch b/target/linux/layerscape/patches-4.9/817-usb-support-layerscape.patch index 3c278099d3..b170fa93a2 100644 --- a/target/linux/layerscape/patches-4.9/817-usb-support-layerscape.patch +++ b/target/linux/layerscape/patches-4.9/817-usb-support-layerscape.patch @@ -1,7 +1,7 @@ -From a2a97f0d2c07a772899ca09967547bea6c9124c5 Mon Sep 17 00:00:00 2001 +From 1d35e363dd6e8bb1733bca0dfc186e3f70e692fe Mon Sep 17 00:00:00 2001 From: Yangbo Lu <yangbo.lu@nxp.com> -Date: Wed, 17 Jan 2018 15:46:03 +0800 -Subject: [PATCH 29/30] usb: support layerscape +Date: Thu, 5 Jul 2018 17:38:52 +0800 +Subject: [PATCH 29/32] usb: support layerscape This is an integrated patch for layerscape usb support. @@ -17,30 +17,31 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> --- drivers/net/usb/cdc_ether.c | 8 + drivers/net/usb/r8152.c | 6 + - drivers/usb/common/common.c | 50 ++++++ + drivers/usb/common/common.c | 50 +++++ drivers/usb/core/hub.c | 8 + - drivers/usb/dwc3/core.c | 243 ++++++++++++++++++++++++++++- - drivers/usb/dwc3/core.h | 51 ++++++- + drivers/usb/dwc3/core.c | 243 +++++++++++++++++++++- + drivers/usb/dwc3/core.h | 51 ++++- drivers/usb/dwc3/ep0.c | 4 +- drivers/usb/dwc3/gadget.c | 7 + drivers/usb/dwc3/host.c | 24 ++- - drivers/usb/gadget/udc/fsl_udc_core.c | 46 +++--- + drivers/usb/gadget/udc/fsl_udc_core.c | 46 +++-- drivers/usb/gadget/udc/fsl_usb2_udc.h | 16 +- - drivers/usb/host/Kconfig | 2 +- - drivers/usb/host/ehci-fsl.c | 279 +++++++++++++++++++++++++++++++--- + drivers/usb/host/Kconfig | 4 +- + drivers/usb/host/ehci-fsl.c | 279 ++++++++++++++++++++++++-- drivers/usb/host/ehci-fsl.h | 3 + drivers/usb/host/ehci-hub.c | 4 + - drivers/usb/host/ehci.h | 9 ++ - drivers/usb/host/fsl-mph-dr-of.c | 12 ++ - drivers/usb/host/xhci-plat.c | 10 ++ - drivers/usb/host/xhci-ring.c | 29 +++- - drivers/usb/host/xhci.c | 38 ++++- - drivers/usb/host/xhci.h | 5 +- - drivers/usb/phy/phy-fsl-usb.c | 59 +++++-- + drivers/usb/host/ehci.h | 9 + + drivers/usb/host/fsl-mph-dr-of.c | 16 +- + drivers/usb/host/xhci-hub.c | 22 ++ + drivers/usb/host/xhci-plat.c | 16 +- + drivers/usb/host/xhci-ring.c | 29 ++- + drivers/usb/host/xhci.c | 38 +++- + drivers/usb/host/xhci.h | 6 +- + drivers/usb/phy/phy-fsl-usb.c | 59 ++++-- drivers/usb/phy/phy-fsl-usb.h | 8 + include/linux/usb.h | 1 + include/linux/usb/of.h | 2 + - 25 files changed, 836 insertions(+), 88 deletions(-) + 26 files changed, 867 insertions(+), 92 deletions(-) --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -924,11 +925,13 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> #endif --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig -@@ -165,7 +165,7 @@ config XPS_USB_HCD_XILINX +@@ -164,8 +164,8 @@ config XPS_USB_HCD_XILINX + devices only. config USB_EHCI_FSL - tristate "Support for Freescale PPC on-chip EHCI USB controller" +- tristate "Support for Freescale PPC on-chip EHCI USB controller" - depends on FSL_SOC ++ tristate "Support for Freescale QorIQ(ARM/PPC) on-chip EHCI USB controller" + depends on USB_EHCI_HCD select USB_EHCI_ROOT_HUB_TT ---help--- @@ -1399,6 +1402,17 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> /* --- a/drivers/usb/host/fsl-mph-dr-of.c +++ b/drivers/usb/host/fsl-mph-dr-of.c +@@ -98,8 +98,8 @@ static struct platform_device *fsl_usb2_ + + pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask; + +- if (!pdev->dev.dma_mask) +- pdev->dev.dma_mask = &ofdev->dev.coherent_dma_mask; ++ if (!pdev->dev.dma_mask && ofdev->dev.of_node) ++ of_dma_configure(&pdev->dev, ofdev->dev.of_node); + else + dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); + @@ -226,6 +226,18 @@ static int fsl_usb2_mph_dr_of_probe(stru of_property_read_bool(np, "fsl,usb-erratum-a007792"); pdata->has_fsl_erratum_a005275 = @@ -1418,12 +1432,57 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> /* * Determine whether phy_clk_valid needs to be checked +--- a/drivers/usb/host/xhci-hub.c ++++ b/drivers/usb/host/xhci-hub.c +@@ -562,12 +562,34 @@ void xhci_set_link_state(struct xhci_hcd + int port_id, u32 link_state) + { + u32 temp; ++ u32 portpmsc_u2_backup = 0; ++ ++ /* Backup U2 timeout info before initiating U3 entry erratum A-010131 */ ++ if (xhci->shared_hcd->speed >= HCD_USB3 && ++ link_state == USB_SS_PORT_LS_U3 && ++ (xhci->quirks & XHCI_DIS_U1U2_WHEN_U3)) { ++ portpmsc_u2_backup = readl(port_array[port_id] + PORTPMSC); ++ portpmsc_u2_backup &= PORT_U2_TIMEOUT_MASK; ++ temp = readl(port_array[port_id] + PORTPMSC); ++ temp |= PORT_U2_TIMEOUT_MASK; ++ writel(temp, port_array[port_id] + PORTPMSC); ++ } + + temp = readl(port_array[port_id]); + temp = xhci_port_state_to_neutral(temp); + temp &= ~PORT_PLS_MASK; + temp |= PORT_LINK_STROBE | link_state; + writel(temp, port_array[port_id]); ++ ++ /* Restore U2 timeout info after U3 entry complete */ ++ if (xhci->shared_hcd->speed >= HCD_USB3 && ++ link_state == USB_SS_PORT_LS_U3 && ++ (xhci->quirks & XHCI_DIS_U1U2_WHEN_U3)) { ++ temp = readl(port_array[port_id] + PORTPMSC); ++ temp &= ~PORT_U2_TIMEOUT_MASK; ++ temp |= portpmsc_u2_backup; ++ writel(temp, port_array[port_id] + PORTPMSC); ++ } + } + + static void xhci_set_remote_wake_mask(struct xhci_hcd *xhci, --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c -@@ -223,6 +223,16 @@ static int xhci_plat_probe(struct platfo - if (device_property_read_bool(&pdev->dev, "usb3-lpm-capable")) - xhci->quirks |= XHCI_LPM_SUPPORT; +@@ -220,8 +220,22 @@ static int xhci_plat_probe(struct platfo + goto disable_clk; + } +- if (device_property_read_bool(&pdev->dev, "usb3-lpm-capable")) ++ if (device_property_read_bool(&pdev->dev, "usb3-lpm-capable")) { + xhci->quirks |= XHCI_LPM_SUPPORT; ++ if (device_property_read_bool(&pdev->dev, ++ "snps,dis-u1u2-when-u3-quirk")) ++ xhci->quirks |= XHCI_DIS_U1U2_WHEN_U3; ++ } ++ + if (device_property_read_bool(&pdev->dev, "quirk-reverse-in-out")) + xhci->quirks |= XHCI_REVERSE_IN_OUT; + @@ -1433,10 +1492,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + + if (device_property_read_bool(&pdev->dev, "quirk-stop-ep-in-u1")) + xhci->quirks |= XHCI_STOP_EP_IN_U1; -+ + if (device_property_read_bool(&pdev->dev, "quirk-broken-port-ped")) xhci->quirks |= XHCI_BROKEN_PORT_PED; - --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1852,14 +1852,17 @@ static int finish_td(struct xhci_hcd *xh @@ -1551,13 +1609,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> #define XHCI_LINK_TRB_QUIRK (1 << 0) #define XHCI_RESET_EP_QUIRK (1 << 1) #define XHCI_NEC_HOST (1 << 2) -@@ -1661,6 +1661,9 @@ struct xhci_hcd { +@@ -1661,6 +1661,10 @@ struct xhci_hcd { #define XHCI_SSIC_PORT_UNUSED (1 << 22) #define XHCI_NO_64BIT_SUPPORT (1 << 23) #define XHCI_MISSING_CAS (1 << 24) +#define XHCI_REVERSE_IN_OUT (1 << 29) +#define XHCI_STOP_TRANSFER_IN_BLOCK (1 << 30) +#define XHCI_STOP_EP_IN_U1 (1 << 31) ++#define XHCI_DIS_U1U2_WHEN_U3 (1 << 32) /* For controller with a broken Port Disable implementation */ #define XHCI_BROKEN_PORT_PED (1 << 25) #define XHCI_LIMIT_ENDPOINT_INTERVAL_7 (1 << 26) diff --git a/target/linux/layerscape/patches-4.9/818-vfio-support-layerscape.patch b/target/linux/layerscape/patches-4.9/818-vfio-support-layerscape.patch index 05806a98d0..f2a65ffba5 100644 --- a/target/linux/layerscape/patches-4.9/818-vfio-support-layerscape.patch +++ b/target/linux/layerscape/patches-4.9/818-vfio-support-layerscape.patch @@ -1,7 +1,7 @@ -From 954edeee88305fecefe3f681e67a298f06e27974 Mon Sep 17 00:00:00 2001 +From e6af99cc1d56322fc960d072af1a7e0e9285b90c Mon Sep 17 00:00:00 2001 From: Yangbo Lu <yangbo.lu@nxp.com> -Date: Wed, 17 Jan 2018 15:48:47 +0800 -Subject: [PATCH 30/30] vfio: support layerscape +Date: Thu, 5 Jul 2018 17:39:43 +0800 +Subject: [PATCH 30/32] vfio: support layerscape This is an integrated patch for layerscape vfio support. @@ -15,12 +15,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> drivers/vfio/Makefile | 1 + drivers/vfio/fsl-mc/Kconfig | 9 + drivers/vfio/fsl-mc/Makefile | 2 + - drivers/vfio/fsl-mc/vfio_fsl_mc.c | 753 ++++++++++++++++++++++++++++++ - drivers/vfio/fsl-mc/vfio_fsl_mc_intr.c | 199 ++++++++ - drivers/vfio/fsl-mc/vfio_fsl_mc_private.h | 55 +++ + drivers/vfio/fsl-mc/vfio_fsl_mc.c | 752 ++++++++++++++++++++++ + drivers/vfio/fsl-mc/vfio_fsl_mc_intr.c | 199 ++++++ + drivers/vfio/fsl-mc/vfio_fsl_mc_private.h | 55 ++ drivers/vfio/vfio_iommu_type1.c | 39 +- include/uapi/linux/vfio.h | 1 + - 9 files changed, 1058 insertions(+), 2 deletions(-) + 9 files changed, 1057 insertions(+), 2 deletions(-) create mode 100644 drivers/vfio/fsl-mc/Kconfig create mode 100644 drivers/vfio/fsl-mc/Makefile create mode 100644 drivers/vfio/fsl-mc/vfio_fsl_mc.c @@ -61,7 +61,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +obj-$(CONFIG_VFIO_FSL_MC) += vfio_fsl_mc.o vfio_fsl_mc_intr.o --- /dev/null +++ b/drivers/vfio/fsl-mc/vfio_fsl_mc.c -@@ -0,0 +1,753 @@ +@@ -0,0 +1,752 @@ +/* + * Freescale Management Complex (MC) device passthrough using VFIO + * @@ -83,10 +83,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#include <linux/vfio.h> +#include <linux/delay.h> + -+#include "../../staging/fsl-mc/include/mc.h" -+#include "../../staging/fsl-mc/include/mc-bus.h" -+#include "../../staging/fsl-mc/include/mc-sys.h" -+#include "../../staging/fsl-mc/bus/dprc-cmd.h" ++#include <linux/fsl/mc.h> + +#include "vfio_fsl_mc_private.h" + @@ -353,8 +350,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint64_t data[8]; + int i; + -+ /* Read ioctl supported only for DPRC device */ -+ if (strcmp(vdev->mc_dev->obj_desc.type, "dprc")) ++ /* Read ioctl supported only for DPRC and DPMCP device */ ++ if (strcmp(vdev->mc_dev->obj_desc.type, "dprc") && ++ strcmp(vdev->mc_dev->obj_desc.type, "dpmcp")) + return -EINVAL; + + if (index >= vdev->num_regions) @@ -455,8 +453,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> + uint64_t data[8]; + int ret; + -+ /* Write ioctl supported only for DPRC device */ -+ if (strcmp(vdev->mc_dev->obj_desc.type, "dprc")) ++ /* Write ioctl supported only for DPRC and DPMCP device */ ++ if (strcmp(vdev->mc_dev->obj_desc.type, "dprc") && ++ strcmp(vdev->mc_dev->obj_desc.type, "dpmcp")) + return -EINVAL; + + if (index >= vdev->num_regions) @@ -835,7 +834,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +#include <linux/eventfd.h> +#include <linux/msi.h> + -+#include "../../staging/fsl-mc/include/mc.h" ++#include "linux/fsl/mc.h" +#include "vfio_fsl_mc_private.h" + +static irqreturn_t vfio_fsl_mc_irq_handler(int irq_num, void *arg) diff --git a/target/linux/layerscape/patches-4.9/819-flexcan-support-layerscape.patch b/target/linux/layerscape/patches-4.9/819-flexcan-support-layerscape.patch new file mode 100644 index 0000000000..5b0b3fd88e --- /dev/null +++ b/target/linux/layerscape/patches-4.9/819-flexcan-support-layerscape.patch @@ -0,0 +1,542 @@ +From 2887442bd13bc8be687afc7172cb01c2b7f0dd3b Mon Sep 17 00:00:00 2001 +From: Yangbo Lu <yangbo.lu@nxp.com> +Date: Thu, 5 Jul 2018 17:41:14 +0800 +Subject: [PATCH 31/32] flexcan: support layerscape + +This is an integrated patch for layerscape flexcan support. + +Signed-off-by: Pankaj Bansal <pankaj.bansal@nxp.com> +Signed-off-by: Bhupesh Sharma <bhupesh.sharma@freescale.com> +Signed-off-by: Sakar Arora <Sakar.Arora@freescale.com> +Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +--- + drivers/net/can/flexcan.c | 212 ++++++++++++++++++++++---------------- + 1 file changed, 123 insertions(+), 89 deletions(-) + +--- a/drivers/net/can/flexcan.c ++++ b/drivers/net/can/flexcan.c +@@ -184,6 +184,7 @@ + * MX53 FlexCAN2 03.00.00.00 yes no no no + * MX6s FlexCAN3 10.00.12.00 yes yes no yes + * VF610 FlexCAN3 ? no yes yes yes? ++ * LS1021A FlexCAN2 03.00.04.00 no yes no yes + * + * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected. + */ +@@ -260,6 +261,10 @@ struct flexcan_priv { + struct flexcan_platform_data *pdata; + const struct flexcan_devtype_data *devtype_data; + struct regulator *reg_xceiver; ++ ++ /* Read and Write APIs */ ++ u32 (*read)(void __iomem *addr); ++ void (*write)(u32 val, void __iomem *addr); + }; + + static struct flexcan_devtype_data fsl_p1010_devtype_data = { +@@ -276,6 +281,10 @@ static struct flexcan_devtype_data fsl_v + .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_DISABLE_MECR, + }; + ++static const struct flexcan_devtype_data fsl_ls1021a_r2_devtype_data = { ++ .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_DISABLE_MECR, ++}; ++ + static const struct can_bittiming_const flexcan_bittiming_const = { + .name = DRV_NAME, + .tseg1_min = 4, +@@ -288,32 +297,38 @@ static const struct can_bittiming_const + .brp_inc = 1, + }; + +-/* Abstract off the read/write for arm versus ppc. This +- * assumes that PPC uses big-endian registers and everything +- * else uses little-endian registers, independent of CPU +- * endianness. ++/* FlexCAN module is essentially modelled as a little-endian IP in most ++ * SoCs, i.e the registers as well as the message buffer areas are ++ * implemented in a little-endian fashion. ++ * ++ * However there are some SoCs (e.g. LS1021A) which implement the FlexCAN ++ * module in a big-endian fashion (i.e the registers as well as the ++ * message buffer areas are implemented in a big-endian way). ++ * ++ * In addition, the FlexCAN module can be found on SoCs having ARM or ++ * PPC cores. So, we need to abstract off the register read/write ++ * functions, ensuring that these cater to all the combinations of module ++ * endianness and underlying CPU endianness. + */ +-#if defined(CONFIG_PPC) +-static inline u32 flexcan_read(void __iomem *addr) ++static inline u32 flexcan_read_be(void __iomem *addr) + { +- return in_be32(addr); ++ return ioread32be(addr); + } + +-static inline void flexcan_write(u32 val, void __iomem *addr) ++static inline void flexcan_write_be(u32 val, void __iomem *addr) + { +- out_be32(addr, val); ++ iowrite32be(val, addr); + } +-#else +-static inline u32 flexcan_read(void __iomem *addr) ++ ++static inline u32 flexcan_read_le(void __iomem *addr) + { +- return readl(addr); ++ return ioread32(addr); + } + +-static inline void flexcan_write(u32 val, void __iomem *addr) ++static inline void flexcan_write_le(u32 val, void __iomem *addr) + { +- writel(val, addr); ++ iowrite32(val, addr); + } +-#endif + + static inline int flexcan_transceiver_enable(const struct flexcan_priv *priv) + { +@@ -344,14 +359,14 @@ static int flexcan_chip_enable(struct fl + unsigned int timeout = FLEXCAN_TIMEOUT_US / 10; + u32 reg; + +- reg = flexcan_read(®s->mcr); ++ reg = priv->read(®s->mcr); + reg &= ~FLEXCAN_MCR_MDIS; +- flexcan_write(reg, ®s->mcr); ++ priv->write(reg, ®s->mcr); + +- while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) ++ while (timeout-- && (priv->read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) + udelay(10); + +- if (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK) ++ if (priv->read(®s->mcr) & FLEXCAN_MCR_LPM_ACK) + return -ETIMEDOUT; + + return 0; +@@ -363,14 +378,14 @@ static int flexcan_chip_disable(struct f + unsigned int timeout = FLEXCAN_TIMEOUT_US / 10; + u32 reg; + +- reg = flexcan_read(®s->mcr); ++ reg = priv->read(®s->mcr); + reg |= FLEXCAN_MCR_MDIS; +- flexcan_write(reg, ®s->mcr); ++ priv->write(reg, ®s->mcr); + +- while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) ++ while (timeout-- && !(priv->read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) + udelay(10); + +- if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) ++ if (!(priv->read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) + return -ETIMEDOUT; + + return 0; +@@ -382,14 +397,14 @@ static int flexcan_chip_freeze(struct fl + unsigned int timeout = 1000 * 1000 * 10 / priv->can.bittiming.bitrate; + u32 reg; + +- reg = flexcan_read(®s->mcr); ++ reg = priv->read(®s->mcr); + reg |= FLEXCAN_MCR_HALT; +- flexcan_write(reg, ®s->mcr); ++ priv->write(reg, ®s->mcr); + +- while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) ++ while (timeout-- && !(priv->read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) + udelay(100); + +- if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) ++ if (!(priv->read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) + return -ETIMEDOUT; + + return 0; +@@ -401,14 +416,14 @@ static int flexcan_chip_unfreeze(struct + unsigned int timeout = FLEXCAN_TIMEOUT_US / 10; + u32 reg; + +- reg = flexcan_read(®s->mcr); ++ reg = priv->read(®s->mcr); + reg &= ~FLEXCAN_MCR_HALT; +- flexcan_write(reg, ®s->mcr); ++ priv->write(reg, ®s->mcr); + +- while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) ++ while (timeout-- && (priv->read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) + udelay(10); + +- if (flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK) ++ if (priv->read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK) + return -ETIMEDOUT; + + return 0; +@@ -419,11 +434,11 @@ static int flexcan_chip_softreset(struct + struct flexcan_regs __iomem *regs = priv->regs; + unsigned int timeout = FLEXCAN_TIMEOUT_US / 10; + +- flexcan_write(FLEXCAN_MCR_SOFTRST, ®s->mcr); +- while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_SOFTRST)) ++ priv->write(FLEXCAN_MCR_SOFTRST, ®s->mcr); ++ while (timeout-- && (priv->read(®s->mcr) & FLEXCAN_MCR_SOFTRST)) + udelay(10); + +- if (flexcan_read(®s->mcr) & FLEXCAN_MCR_SOFTRST) ++ if (priv->read(®s->mcr) & FLEXCAN_MCR_SOFTRST) + return -ETIMEDOUT; + + return 0; +@@ -434,7 +449,7 @@ static int __flexcan_get_berr_counter(co + { + const struct flexcan_priv *priv = netdev_priv(dev); + struct flexcan_regs __iomem *regs = priv->regs; +- u32 reg = flexcan_read(®s->ecr); ++ u32 reg = priv->read(®s->ecr); + + bec->txerr = (reg >> 0) & 0xff; + bec->rxerr = (reg >> 8) & 0xff; +@@ -491,24 +506,24 @@ static int flexcan_start_xmit(struct sk_ + + if (cf->can_dlc > 0) { + data = be32_to_cpup((__be32 *)&cf->data[0]); +- flexcan_write(data, ®s->mb[FLEXCAN_TX_BUF_ID].data[0]); ++ priv->write(data, ®s->mb[FLEXCAN_TX_BUF_ID].data[0]); + } + if (cf->can_dlc > 4) { + data = be32_to_cpup((__be32 *)&cf->data[4]); +- flexcan_write(data, ®s->mb[FLEXCAN_TX_BUF_ID].data[1]); ++ priv->write(data, ®s->mb[FLEXCAN_TX_BUF_ID].data[1]); + } + + can_put_echo_skb(skb, dev, 0); + +- flexcan_write(can_id, ®s->mb[FLEXCAN_TX_BUF_ID].can_id); +- flexcan_write(ctrl, ®s->mb[FLEXCAN_TX_BUF_ID].can_ctrl); ++ priv->write(can_id, ®s->mb[FLEXCAN_TX_BUF_ID].can_id); ++ priv->write(ctrl, ®s->mb[FLEXCAN_TX_BUF_ID].can_ctrl); + + /* Errata ERR005829 step8: + * Write twice INACTIVE(0x8) code to first MB. + */ +- flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, ++ priv->write(FLEXCAN_MB_CODE_TX_INACTIVE, + ®s->mb[FLEXCAN_TX_BUF_RESERVED].can_ctrl); +- flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, ++ priv->write(FLEXCAN_MB_CODE_TX_INACTIVE, + ®s->mb[FLEXCAN_TX_BUF_RESERVED].can_ctrl); + + return NETDEV_TX_OK; +@@ -632,8 +647,8 @@ static void flexcan_read_fifo(const stru + struct flexcan_mb __iomem *mb = ®s->mb[0]; + u32 reg_ctrl, reg_id; + +- reg_ctrl = flexcan_read(&mb->can_ctrl); +- reg_id = flexcan_read(&mb->can_id); ++ reg_ctrl = priv->read(&mb->can_ctrl); ++ reg_id = priv->read(&mb->can_id); + if (reg_ctrl & FLEXCAN_MB_CNT_IDE) + cf->can_id = ((reg_id >> 0) & CAN_EFF_MASK) | CAN_EFF_FLAG; + else +@@ -643,12 +658,12 @@ static void flexcan_read_fifo(const stru + cf->can_id |= CAN_RTR_FLAG; + cf->can_dlc = get_can_dlc((reg_ctrl >> 16) & 0xf); + +- *(__be32 *)(cf->data + 0) = cpu_to_be32(flexcan_read(&mb->data[0])); +- *(__be32 *)(cf->data + 4) = cpu_to_be32(flexcan_read(&mb->data[1])); ++ *(__be32 *)(cf->data + 0) = cpu_to_be32(priv->read(&mb->data[0])); ++ *(__be32 *)(cf->data + 4) = cpu_to_be32(priv->read(&mb->data[1])); + + /* mark as read */ +- flexcan_write(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, ®s->iflag1); +- flexcan_read(®s->timer); ++ priv->write(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, ®s->iflag1); ++ priv->read(®s->timer); + } + + static int flexcan_read_frame(struct net_device *dev) +@@ -685,17 +700,17 @@ static int flexcan_poll(struct napi_stru + /* The error bits are cleared on read, + * use saved value from irq handler. + */ +- reg_esr = flexcan_read(®s->esr) | priv->reg_esr; ++ reg_esr = priv->read(®s->esr) | priv->reg_esr; + + /* handle state changes */ + work_done += flexcan_poll_state(dev, reg_esr); + + /* handle RX-FIFO */ +- reg_iflag1 = flexcan_read(®s->iflag1); ++ reg_iflag1 = priv->read(®s->iflag1); + while (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE && + work_done < quota) { + work_done += flexcan_read_frame(dev); +- reg_iflag1 = flexcan_read(®s->iflag1); ++ reg_iflag1 = priv->read(®s->iflag1); + } + + /* report bus errors */ +@@ -705,8 +720,8 @@ static int flexcan_poll(struct napi_stru + if (work_done < quota) { + napi_complete_done(napi, work_done); + /* enable IRQs */ +- flexcan_write(FLEXCAN_IFLAG_DEFAULT, ®s->imask1); +- flexcan_write(priv->reg_ctrl_default, ®s->ctrl); ++ priv->write(FLEXCAN_IFLAG_DEFAULT, ®s->imask1); ++ priv->write(priv->reg_ctrl_default, ®s->ctrl); + } + + return work_done; +@@ -720,12 +735,12 @@ static irqreturn_t flexcan_irq(int irq, + struct flexcan_regs __iomem *regs = priv->regs; + u32 reg_iflag1, reg_esr; + +- reg_iflag1 = flexcan_read(®s->iflag1); +- reg_esr = flexcan_read(®s->esr); ++ reg_iflag1 = priv->read(®s->iflag1); ++ reg_esr = priv->read(®s->esr); + + /* ACK all bus error and state change IRQ sources */ + if (reg_esr & FLEXCAN_ESR_ALL_INT) +- flexcan_write(reg_esr & FLEXCAN_ESR_ALL_INT, ®s->esr); ++ priv->write(reg_esr & FLEXCAN_ESR_ALL_INT, ®s->esr); + + /* schedule NAPI in case of: + * - rx IRQ +@@ -739,16 +754,16 @@ static irqreturn_t flexcan_irq(int irq, + * save them for later use. + */ + priv->reg_esr = reg_esr & FLEXCAN_ESR_ERR_BUS; +- flexcan_write(FLEXCAN_IFLAG_DEFAULT & ++ priv->write(FLEXCAN_IFLAG_DEFAULT & + ~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, ®s->imask1); +- flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL, ++ priv->write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL, + ®s->ctrl); + napi_schedule(&priv->napi); + } + + /* FIFO overflow */ + if (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_OVERFLOW) { +- flexcan_write(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW, ®s->iflag1); ++ priv->write(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW, ®s->iflag1); + dev->stats.rx_over_errors++; + dev->stats.rx_errors++; + } +@@ -760,9 +775,9 @@ static irqreturn_t flexcan_irq(int irq, + can_led_event(dev, CAN_LED_EVENT_TX); + + /* after sending a RTR frame MB is in RX mode */ +- flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, ++ priv->write(FLEXCAN_MB_CODE_TX_INACTIVE, + ®s->mb[FLEXCAN_TX_BUF_ID].can_ctrl); +- flexcan_write((1 << FLEXCAN_TX_BUF_ID), ®s->iflag1); ++ priv->write((1 << FLEXCAN_TX_BUF_ID), ®s->iflag1); + netif_wake_queue(dev); + } + +@@ -776,7 +791,7 @@ static void flexcan_set_bittiming(struct + struct flexcan_regs __iomem *regs = priv->regs; + u32 reg; + +- reg = flexcan_read(®s->ctrl); ++ reg = priv->read(®s->ctrl); + reg &= ~(FLEXCAN_CTRL_PRESDIV(0xff) | + FLEXCAN_CTRL_RJW(0x3) | + FLEXCAN_CTRL_PSEG1(0x7) | +@@ -800,11 +815,11 @@ static void flexcan_set_bittiming(struct + reg |= FLEXCAN_CTRL_SMP; + + netdev_dbg(dev, "writing ctrl=0x%08x\n", reg); +- flexcan_write(reg, ®s->ctrl); ++ priv->write(reg, ®s->ctrl); + + /* print chip status */ + netdev_dbg(dev, "%s: mcr=0x%08x ctrl=0x%08x\n", __func__, +- flexcan_read(®s->mcr), flexcan_read(®s->ctrl)); ++ priv->read(®s->mcr), priv->read(®s->ctrl)); + } + + /* flexcan_chip_start +@@ -842,13 +857,13 @@ static int flexcan_chip_start(struct net + * choose format C + * set max mailbox number + */ +- reg_mcr = flexcan_read(®s->mcr); ++ reg_mcr = priv->read(®s->mcr); + reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff); + reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT | + FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_SRX_DIS | + FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_MAXMB(FLEXCAN_TX_BUF_ID); + netdev_dbg(dev, "%s: writing mcr=0x%08x", __func__, reg_mcr); +- flexcan_write(reg_mcr, ®s->mcr); ++ priv->write(reg_mcr, ®s->mcr); + + /* CTRL + * +@@ -861,7 +876,7 @@ static int flexcan_chip_start(struct net + * enable bus off interrupt + * (== FLEXCAN_CTRL_ERR_STATE) + */ +- reg_ctrl = flexcan_read(®s->ctrl); ++ reg_ctrl = priv->read(®s->ctrl); + reg_ctrl &= ~FLEXCAN_CTRL_TSYN; + reg_ctrl |= FLEXCAN_CTRL_BOFF_REC | FLEXCAN_CTRL_LBUF | + FLEXCAN_CTRL_ERR_STATE; +@@ -881,29 +896,29 @@ static int flexcan_chip_start(struct net + /* leave interrupts disabled for now */ + reg_ctrl &= ~FLEXCAN_CTRL_ERR_ALL; + netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl); +- flexcan_write(reg_ctrl, ®s->ctrl); ++ priv->write(reg_ctrl, ®s->ctrl); + + /* clear and invalidate all mailboxes first */ + for (i = FLEXCAN_TX_BUF_ID; i < ARRAY_SIZE(regs->mb); i++) { +- flexcan_write(FLEXCAN_MB_CODE_RX_INACTIVE, ++ priv->write(FLEXCAN_MB_CODE_RX_INACTIVE, + ®s->mb[i].can_ctrl); + } + + /* Errata ERR005829: mark first TX mailbox as INACTIVE */ +- flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, ++ priv->write(FLEXCAN_MB_CODE_TX_INACTIVE, + ®s->mb[FLEXCAN_TX_BUF_RESERVED].can_ctrl); + + /* mark TX mailbox as INACTIVE */ +- flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, ++ priv->write(FLEXCAN_MB_CODE_TX_INACTIVE, + ®s->mb[FLEXCAN_TX_BUF_ID].can_ctrl); + + /* acceptance mask/acceptance code (accept everything) */ +- flexcan_write(0x0, ®s->rxgmask); +- flexcan_write(0x0, ®s->rx14mask); +- flexcan_write(0x0, ®s->rx15mask); ++ priv->write(0x0, ®s->rxgmask); ++ priv->write(0x0, ®s->rx14mask); ++ priv->write(0x0, ®s->rx15mask); + + if (priv->devtype_data->quirks & FLEXCAN_QUIRK_DISABLE_RXFG) +- flexcan_write(0x0, ®s->rxfgmask); ++ priv->write(0x0, ®s->rxfgmask); + + /* On Vybrid, disable memory error detection interrupts + * and freeze mode. +@@ -916,16 +931,16 @@ static int flexcan_chip_start(struct net + * and Correction of Memory Errors" to write to + * MECR register + */ +- reg_ctrl2 = flexcan_read(®s->ctrl2); ++ reg_ctrl2 = priv->read(®s->ctrl2); + reg_ctrl2 |= FLEXCAN_CTRL2_ECRWRE; +- flexcan_write(reg_ctrl2, ®s->ctrl2); ++ priv->write(reg_ctrl2, ®s->ctrl2); + +- reg_mecr = flexcan_read(®s->mecr); ++ reg_mecr = priv->read(®s->mecr); + reg_mecr &= ~FLEXCAN_MECR_ECRWRDIS; +- flexcan_write(reg_mecr, ®s->mecr); ++ priv->write(reg_mecr, ®s->mecr); + reg_mecr &= ~(FLEXCAN_MECR_NCEFAFRZ | FLEXCAN_MECR_HANCEI_MSK | + FLEXCAN_MECR_FANCEI_MSK); +- flexcan_write(reg_mecr, ®s->mecr); ++ priv->write(reg_mecr, ®s->mecr); + } + + err = flexcan_transceiver_enable(priv); +@@ -941,13 +956,13 @@ static int flexcan_chip_start(struct net + + /* enable interrupts atomically */ + disable_irq(dev->irq); +- flexcan_write(priv->reg_ctrl_default, ®s->ctrl); +- flexcan_write(FLEXCAN_IFLAG_DEFAULT, ®s->imask1); ++ priv->write(priv->reg_ctrl_default, ®s->ctrl); ++ priv->write(FLEXCAN_IFLAG_DEFAULT, ®s->imask1); + enable_irq(dev->irq); + + /* print chip status */ + netdev_dbg(dev, "%s: reading mcr=0x%08x ctrl=0x%08x\n", __func__, +- flexcan_read(®s->mcr), flexcan_read(®s->ctrl)); ++ priv->read(®s->mcr), priv->read(®s->ctrl)); + + return 0; + +@@ -972,8 +987,8 @@ static void flexcan_chip_stop(struct net + flexcan_chip_disable(priv); + + /* Disable all interrupts */ +- flexcan_write(0, ®s->imask1); +- flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL, ++ priv->write(0, ®s->imask1); ++ priv->write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL, + ®s->ctrl); + + flexcan_transceiver_disable(priv); +@@ -1089,25 +1104,25 @@ static int register_flexcandev(struct ne + err = flexcan_chip_disable(priv); + if (err) + goto out_disable_per; +- reg = flexcan_read(®s->ctrl); ++ reg = priv->read(®s->ctrl); + reg |= FLEXCAN_CTRL_CLK_SRC; +- flexcan_write(reg, ®s->ctrl); ++ priv->write(reg, ®s->ctrl); + + err = flexcan_chip_enable(priv); + if (err) + goto out_chip_disable; + + /* set freeze, halt and activate FIFO, restrict register access */ +- reg = flexcan_read(®s->mcr); ++ reg = priv->read(®s->mcr); + reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT | + FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV; +- flexcan_write(reg, ®s->mcr); ++ priv->write(reg, ®s->mcr); + + /* Currently we only support newer versions of this core + * featuring a RX FIFO. Older cores found on some Coldfire + * derivates are not yet supported. + */ +- reg = flexcan_read(®s->mcr); ++ reg = priv->read(®s->mcr); + if (!(reg & FLEXCAN_MCR_FEN)) { + netdev_err(dev, "Could not enable RX FIFO, unsupported core\n"); + err = -ENODEV; +@@ -1135,8 +1150,12 @@ static void unregister_flexcandev(struct + static const struct of_device_id flexcan_of_match[] = { + { .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, }, + { .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, }, ++ { .compatible = "fsl,imx53-flexcan", .data = &fsl_p1010_devtype_data, }, ++ { .compatible = "fsl,imx35-flexcan", .data = &fsl_p1010_devtype_data, }, ++ { .compatible = "fsl,imx25-flexcan", .data = &fsl_p1010_devtype_data, }, + { .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, }, + { .compatible = "fsl,vf610-flexcan", .data = &fsl_vf610_devtype_data, }, ++ { .compatible = "fsl,ls1021ar2-flexcan", .data = &fsl_ls1021a_r2_devtype_data, }, + { /* sentinel */ }, + }; + MODULE_DEVICE_TABLE(of, flexcan_of_match); +@@ -1213,6 +1232,21 @@ static int flexcan_probe(struct platform + dev->flags |= IFF_ECHO; + + priv = netdev_priv(dev); ++ ++ if (of_property_read_bool(pdev->dev.of_node, "big-endian")) { ++ priv->read = flexcan_read_be; ++ priv->write = flexcan_write_be; ++ } else { ++ if (of_device_is_compatible(pdev->dev.of_node, ++ "fsl,p1010-flexcan")) { ++ priv->read = flexcan_read_be; ++ priv->write = flexcan_write_be; ++ } else { ++ priv->read = flexcan_read_le; ++ priv->write = flexcan_write_le; ++ } ++ } ++ + priv->can.clock.freq = clock_freq; + priv->can.bittiming_const = &flexcan_bittiming_const; + priv->can.do_set_mode = flexcan_set_mode; diff --git a/target/linux/layerscape/patches-4.9/820-kvm-support-layerscape.patch b/target/linux/layerscape/patches-4.9/820-kvm-support-layerscape.patch new file mode 100644 index 0000000000..a652660f9a --- /dev/null +++ b/target/linux/layerscape/patches-4.9/820-kvm-support-layerscape.patch @@ -0,0 +1,239 @@ +From fe22151c95c02c6bb145ea6c3685941e8fb09d60 Mon Sep 17 00:00:00 2001 +From: Yangbo Lu <yangbo.lu@nxp.com> +Date: Thu, 5 Jul 2018 17:43:16 +0800 +Subject: [PATCH 32/32] kvm: support layerscape + +This is an integrated patch for layerscape kvm support. + +Signed-off-by: Laurentiu Tudor <laurentiu.tudor@nxp.com> +Signed-off-by: Bharat Bhushan <Bharat.Bhushan@nxp.com> +Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com> +Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> +--- + arch/arm/include/asm/kvm_mmu.h | 3 +- + arch/arm/kvm/mmu.c | 56 ++++++++++++++++++++++++++++++-- + arch/arm64/include/asm/kvm_mmu.h | 14 ++++++-- + virt/kvm/arm/vgic/vgic-its.c | 24 +++++++++++--- + virt/kvm/arm/vgic/vgic-v2.c | 3 +- + 5 files changed, 88 insertions(+), 12 deletions(-) + +--- a/arch/arm/include/asm/kvm_mmu.h ++++ b/arch/arm/include/asm/kvm_mmu.h +@@ -55,7 +55,8 @@ void stage2_unmap_vm(struct kvm *kvm); + int kvm_alloc_stage2_pgd(struct kvm *kvm); + void kvm_free_stage2_pgd(struct kvm *kvm); + int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa, +- phys_addr_t pa, unsigned long size, bool writable); ++ phys_addr_t pa, unsigned long size, bool writable, ++ pgprot_t prot); + + int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run); + +--- a/arch/arm/kvm/mmu.c ++++ b/arch/arm/kvm/mmu.c +@@ -1020,9 +1020,11 @@ static int stage2_pmdp_test_and_clear_yo + * @guest_ipa: The IPA at which to insert the mapping + * @pa: The physical address of the device + * @size: The size of the mapping ++ * @prot: S2 page translation bits + */ + int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa, +- phys_addr_t pa, unsigned long size, bool writable) ++ phys_addr_t pa, unsigned long size, bool writable, ++ pgprot_t prot) + { + phys_addr_t addr, end; + int ret = 0; +@@ -1033,7 +1035,7 @@ int kvm_phys_addr_ioremap(struct kvm *kv + pfn = __phys_to_pfn(pa); + + for (addr = guest_ipa; addr < end; addr += PAGE_SIZE) { +- pte_t pte = pfn_pte(pfn, PAGE_S2_DEVICE); ++ pte_t pte = pfn_pte(pfn, prot); + + if (writable) + pte = kvm_s2pte_mkwrite(pte); +@@ -1057,6 +1059,30 @@ out: + return ret; + } + ++#ifdef CONFIG_ARM64 ++static pgprot_t stage1_to_stage2_pgprot(pgprot_t prot) ++{ ++ switch (pgprot_val(prot) & PTE_ATTRINDX_MASK) { ++ case PTE_ATTRINDX(MT_DEVICE_nGnRE): ++ case PTE_ATTRINDX(MT_DEVICE_nGnRnE): ++ case PTE_ATTRINDX(MT_DEVICE_GRE): ++ return PAGE_S2_DEVICE; ++ case PTE_ATTRINDX(MT_NORMAL_NC): ++ case PTE_ATTRINDX(MT_NORMAL): ++ return (pgprot_val(prot) & PTE_SHARED) ++ ? PAGE_S2 ++ : PAGE_S2_NS; ++ } ++ ++ return PAGE_S2_DEVICE; ++} ++#else ++static pgprot_t stage1_to_stage2_pgprot(pgprot_t prot) ++{ ++ return PAGE_S2_DEVICE; ++} ++#endif ++ + static bool transparent_hugepage_adjust(kvm_pfn_t *pfnp, phys_addr_t *ipap) + { + kvm_pfn_t pfn = *pfnp; +@@ -1308,6 +1334,19 @@ static int user_mem_abort(struct kvm_vcp + hugetlb = true; + gfn = (fault_ipa & PMD_MASK) >> PAGE_SHIFT; + } else { ++ if (!is_vm_hugetlb_page(vma)) { ++ pte_t *pte; ++ spinlock_t *ptl; ++ pgprot_t prot; ++ ++ pte = get_locked_pte(current->mm, memslot->userspace_addr, &ptl); ++ prot = stage1_to_stage2_pgprot(__pgprot(pte_val(*pte))); ++ pte_unmap_unlock(pte, ptl); ++#ifdef CONFIG_ARM64 ++ if (pgprot_val(prot) == pgprot_val(PAGE_S2_NS)) ++ mem_type = PAGE_S2_NS; ++#endif ++ } + /* + * Pages belonging to memslots that don't have the same + * alignment for userspace and IPA cannot be mapped using +@@ -1345,6 +1384,11 @@ static int user_mem_abort(struct kvm_vcp + if (is_error_noslot_pfn(pfn)) + return -EFAULT; + ++#ifdef CONFIG_ARM64 ++ if (pgprot_val(mem_type) == pgprot_val(PAGE_S2_NS)) { ++ flags |= KVM_S2PTE_FLAG_IS_IOMAP; ++ } else ++#endif + if (kvm_is_device_pfn(pfn)) { + mem_type = PAGE_S2_DEVICE; + flags |= KVM_S2PTE_FLAG_IS_IOMAP; +@@ -1882,6 +1926,9 @@ int kvm_arch_prepare_memory_region(struc + gpa_t gpa = mem->guest_phys_addr + + (vm_start - mem->userspace_addr); + phys_addr_t pa; ++ pgprot_t prot; ++ pte_t *pte; ++ spinlock_t *ptl; + + pa = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT; + pa += vm_start - vma->vm_start; +@@ -1891,10 +1938,13 @@ int kvm_arch_prepare_memory_region(struc + ret = -EINVAL; + goto out; + } ++ pte = get_locked_pte(current->mm, mem->userspace_addr, &ptl); ++ prot = stage1_to_stage2_pgprot(__pgprot(pte_val(*pte))); ++ pte_unmap_unlock(pte, ptl); + + ret = kvm_phys_addr_ioremap(kvm, gpa, pa, + vm_end - vm_start, +- writable); ++ writable, prot); + if (ret) + break; + } +--- a/arch/arm64/include/asm/kvm_mmu.h ++++ b/arch/arm64/include/asm/kvm_mmu.h +@@ -167,7 +167,8 @@ void stage2_unmap_vm(struct kvm *kvm); + int kvm_alloc_stage2_pgd(struct kvm *kvm); + void kvm_free_stage2_pgd(struct kvm *kvm); + int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa, +- phys_addr_t pa, unsigned long size, bool writable); ++ phys_addr_t pa, unsigned long size, bool writable, ++ pgprot_t prot); + + int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run); + +@@ -274,8 +275,15 @@ static inline void __coherent_cache_gues + + static inline void __kvm_flush_dcache_pte(pte_t pte) + { +- struct page *page = pte_page(pte); +- kvm_flush_dcache_to_poc(page_address(page), PAGE_SIZE); ++ if (pfn_valid(pte_pfn(pte))) { ++ struct page *page = pte_page(pte); ++ kvm_flush_dcache_to_poc(page_address(page), PAGE_SIZE); ++ } else { ++ void __iomem *va = ioremap_cache_ns(pte_pfn(pte) << PAGE_SHIFT, PAGE_SIZE); ++ ++ kvm_flush_dcache_to_poc(va, PAGE_SIZE); ++ iounmap(va); ++ } + } + + static inline void __kvm_flush_dcache_pmd(pmd_t pmd) +--- a/virt/kvm/arm/vgic/vgic-its.c ++++ b/virt/kvm/arm/vgic/vgic-its.c +@@ -176,6 +176,8 @@ static struct its_itte *find_itte(struct + + #define GIC_LPI_OFFSET 8192 + ++#define VITS_TYPER_DEVBITS 17 ++ + /* + * Finds and returns a collection in the ITS collection table. + * Must be called with the its_lock mutex held. +@@ -375,7 +377,7 @@ static unsigned long vgic_mmio_read_its_ + * To avoid memory waste in the guest, we keep the number of IDBits and + * DevBits low - as least for the time being. + */ +- reg |= 0x0f << GITS_TYPER_DEVBITS_SHIFT; ++ reg |= GIC_ENCODE_SZ(VITS_TYPER_DEVBITS, 5) << GITS_TYPER_DEVBITS_SHIFT; + reg |= 0x0f << GITS_TYPER_IDBITS_SHIFT; + + return extract_bytes(reg, addr & 7, len); +@@ -601,16 +603,30 @@ static int vgic_its_cmd_handle_movi(stru + * Check whether an ID can be stored into the corresponding guest table. + * For a direct table this is pretty easy, but gets a bit nasty for + * indirect tables. We check whether the resulting guest physical address +- * is actually valid (covered by a memslot and guest accessbible). ++ * is actually valid (covered by a memslot and guest accessible). + * For this we have to read the respective first level entry. + */ +-static bool vgic_its_check_id(struct vgic_its *its, u64 baser, int id) ++static bool vgic_its_check_id(struct vgic_its *its, u64 baser, u32 id) + { + int l1_tbl_size = GITS_BASER_NR_PAGES(baser) * SZ_64K; ++ u64 indirect_ptr, type = GITS_BASER_TYPE(baser); + int index; +- u64 indirect_ptr; + gfn_t gfn; + ++ switch (type) { ++ case GITS_BASER_TYPE_DEVICE: ++ if (id >= BIT_ULL(VITS_TYPER_DEVBITS)) ++ return false; ++ break; ++ case GITS_BASER_TYPE_COLLECTION: ++ /* as GITS_TYPER.CIL == 0, ITS supports 16-bit collection ID */ ++ if (id >= BIT_ULL(16)) ++ return false; ++ break; ++ default: ++ return false; ++ } ++ + if (!(baser & GITS_BASER_INDIRECT)) { + phys_addr_t addr; + +--- a/virt/kvm/arm/vgic/vgic-v2.c ++++ b/virt/kvm/arm/vgic/vgic-v2.c +@@ -290,7 +290,8 @@ int vgic_v2_map_resources(struct kvm *kv + if (!static_branch_unlikely(&vgic_v2_cpuif_trap)) { + ret = kvm_phys_addr_ioremap(kvm, dist->vgic_cpu_base, + kvm_vgic_global_state.vcpu_base, +- KVM_VGIC_V2_CPU_SIZE, true); ++ KVM_VGIC_V2_CPU_SIZE, true, ++ PAGE_S2_DEVICE); + if (ret) { + kvm_err("Unable to remap VGIC CPU to VCPU\n"); + goto out; diff --git a/target/linux/layerscape/patches-4.9/820-rgmii-fixed-link.patch b/target/linux/layerscape/patches-4.9/822-rgmii-fixed-link.patch index 593bd3e79a..593bd3e79a 100644 --- a/target/linux/layerscape/patches-4.9/820-rgmii-fixed-link.patch +++ b/target/linux/layerscape/patches-4.9/822-rgmii-fixed-link.patch |